plugins: implement plugin unregister
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 16 Oct 2012 22:04:39 +0000 (18:04 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 16 Oct 2012 22:04:39 +0000 (18:04 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
formats/bt-dummy/bt-dummy.c
formats/ctf-text/ctf-text.c
formats/ctf/ctf.c
include/babeltrace/format.h
lib/registry.c

index 2e94421f7366759b350608d15b7fb33924014fd5..94edc3be83742ec82b672f157f8678df1670f446 100644 (file)
@@ -74,4 +74,8 @@ void __attribute__((constructor)) bt_dummy_init(void)
        assert(!ret);
 }
 
-/* TODO: finalize */
+static
+void __attribute__((destructor)) bt_dummy_exit(void)
+{
+       bt_unregister_format(&bt_dummy_format);
+}
index 40f2f008c5ad12d853b08c958e17b2f4309821bc..cbf074e07e76db4f03bfd028803ffbdf94745081 100644 (file)
@@ -78,10 +78,11 @@ enum bt_loglevel {
         BT_LOGLEVEL_DEBUG                  = 14,
 };
 
-
+static
 struct trace_descriptor *ctf_text_open_trace(const char *path, int flags,
                void (*packet_seek)(struct stream_pos *pos, size_t index,
                        int whence), FILE *metadata_fp);
+static
 void ctf_text_close_trace(struct trace_descriptor *descriptor);
 
 static
@@ -545,7 +546,7 @@ error:
        return ret;
 }
 
-
+static
 struct trace_descriptor *ctf_text_open_trace(const char *path, int flags,
                void (*packet_seek)(struct stream_pos *pos, size_t index,
                        int whence), FILE *metadata_fp)
@@ -582,6 +583,7 @@ error:
        return NULL;
 }
 
+static
 void ctf_text_close_trace(struct trace_descriptor *td)
 {
        struct ctf_text_stream_pos *pos =
@@ -590,6 +592,7 @@ void ctf_text_close_trace(struct trace_descriptor *td)
        g_free(pos);
 }
 
+static
 void __attribute__((constructor)) ctf_text_init(void)
 {
        int ret;
@@ -599,4 +602,8 @@ void __attribute__((constructor)) ctf_text_init(void)
        assert(!ret);
 }
 
-/* TODO: finalize */
+static
+void __attribute__((destructor)) ctf_text_exit(void)
+{
+       bt_unregister_format(&ctf_text_format);
+}
index e59e3573b8709b6440e37f8560ca3dfe1e737298..b07c45c3d8de3b334577af85569fa099f373d445 100644 (file)
@@ -1935,6 +1935,7 @@ void ctf_set_handle(struct trace_descriptor *descriptor,
        td->handle = handle;
 }
 
+static
 void __attribute__((constructor)) ctf_init(void)
 {
        int ret;
@@ -1944,4 +1945,8 @@ void __attribute__((constructor)) ctf_init(void)
        assert(!ret);
 }
 
-/* TODO: finalize */
+static
+void __attribute__((destructor)) ctf_exit(void)
+{
+       bt_unregister_format(&ctf_format);
+}
index ef340da115b9432abdad0f35d6e5e94a3d23e52b..5de52fcf73d0ef99a8f401dc50bcfd3c88207e46 100644 (file)
@@ -77,8 +77,8 @@ struct format {
 extern struct format *bt_lookup_format(bt_intern_str qname);
 extern void bt_fprintf_format_list(FILE *fp);
 extern int bt_register_format(struct format *format);
+extern void bt_unregister_format(struct format *format);
 
-/* TBD: format unregistration */
 #ifdef __cplusplus
 }
 #endif
index 3cef63d93cb0966b783819b6e402201303062ab1..4d09e5db079837e04df86450d3772399648e2d2a 100644 (file)
@@ -29,16 +29,35 @@ struct walk_data {
        int iter;
 };
 
-static int init_done;
-void __attribute__((constructor)) format_init(void);
-void __attribute__((destructor)) format_finalize(void);
-
 /*
  * Format registry hash table contains the registered formats. Format
  * registration is typically performed by a format plugin.
- * TODO: support plugin unload (unregistration of formats).
  */
-GHashTable *format_registry;
+static GHashTable *format_registry;
+static int format_refcount;
+static int init_done;
+
+static __attribute__((constructor)) void format_init(void);
+
+static
+void format_refcount_inc(void)
+{
+       format_refcount++;
+}
+
+static
+void format_cleanup(void)
+{
+       if (format_registry)
+               g_hash_table_destroy(format_registry);
+}
+
+static
+void format_refcount_dec(void)
+{
+       if (!--format_refcount)
+               format_cleanup();
+}
 
 struct format *bt_lookup_format(bt_intern_str name)
 {
@@ -87,22 +106,41 @@ int bt_register_format(struct format *format)
        if (bt_lookup_format(format->name))
                return -EEXIST;
 
+       format_refcount_inc();
        g_hash_table_insert(format_registry,
                            (gpointer) (unsigned long) format->name,
                            format);
        return 0;
 }
 
+void bt_unregister_format(struct format *format)
+{
+       assert(bt_lookup_format(format->name));
+       g_hash_table_remove(format_registry,
+                           (gpointer) (unsigned long) format->name);
+       format_refcount_dec();
+}
+
+/*
+ * We cannot assume that the constructor and destructor order will be
+ * right: another library might be loaded before us, and initialize us
+ * from bt_register_format(). This is why we use a reference count to
+ * handle cleanup of this module. The format_finalize destructor
+ * refcount decrement matches format_init refcount increment.
+ */
+static __attribute__((constructor))
 void format_init(void)
 {
        if (init_done)
                return;
+       format_refcount_inc();
        format_registry = g_hash_table_new(g_direct_hash, g_direct_equal);
        assert(format_registry);
        init_done = 1;
 }
 
+static __attribute__((destructor))
 void format_finalize(void)
 {
-       g_hash_table_destroy(format_registry);
+       format_refcount_dec();
 }
This page took 0.038794 seconds and 4 git commands to generate.