X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=blobdiff_plain;f=lib%2Fregistry.c;fp=lib%2Fregistry.c;h=4d09e5db079837e04df86450d3772399648e2d2a;hp=3cef63d93cb0966b783819b6e402201303062ab1;hb=95febab3a71bc0d64d9ebd0ce08787d96a51d475;hpb=4963668994aa255cd9e938eab6e504b07817f79a diff --git a/lib/registry.c b/lib/registry.c index 3cef63d9..4d09e5db 100644 --- a/lib/registry.c +++ b/lib/registry.c @@ -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(); }