From 8e00b10d134e4fb844cdc961e5c3230edf194b57 Mon Sep 17 00:00:00 2001 From: Robert McQueen Date: Fri, 27 Jan 2006 15:40:36 +0000 Subject: 2006-01-27 Robert McQueen * glib/dbus-gtype-specialized.[ch], glib/dbus-gvalue-utils.c: Patch by me and Rob Taylor to add a simple_free function to D-Bus map and collection types, which allows those types which can be freed with a GDestroyNotify (such as GHashTables and GArrays, but not GPtrArrays) to be stored as the values in hashtables. * test/glib/test-dbus-glib.c, test/glib/test-service-glib.{c,xml}: Patch by Rob Taylor to add nested dicts to the glib tests to check the above code works, and appears not to leak when called repeatedly. --- glib/dbus-gtype-specialized.c | 33 +++++++++++++++++++++++++++- glib/dbus-gtype-specialized.h | 4 +++- glib/dbus-gvalue-utils.c | 50 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 77 insertions(+), 10 deletions(-) (limited to 'glib') diff --git a/glib/dbus-gtype-specialized.c b/glib/dbus-gtype-specialized.c index ccf65eef..ad93a8c5 100644 --- a/glib/dbus-gtype-specialized.c +++ b/glib/dbus-gtype-specialized.c @@ -91,7 +91,15 @@ proxy_value_free (GValue *value) data = lookup_specialization_data (type); g_assert (data != NULL); - data->klass->vtable->free_func (type, value->data[0].v_pointer); + if (data->klass->vtable->free_func) + { + data->klass->vtable->free_func (type, value->data[0].v_pointer); + } + else + { + g_assert (data->klass->vtable->simple_free_func != NULL); + data->klass->vtable->simple_free_func (value->data[0].v_pointer); + } } } @@ -227,6 +235,29 @@ dbus_g_type_register_map (const char *name, register_container (name, DBUS_G_SPECTYPE_MAP, (const DBusGTypeSpecializedVtable*) vtable); } +const DBusGTypeSpecializedMapVtable* dbus_g_type_map_peek_vtable (GType map_type) +{ + DBusGTypeSpecializedData *data; + g_return_val_if_fail (dbus_g_type_is_map(map_type), NULL); + + data = lookup_specialization_data (map_type); + g_assert (data != NULL); + + return (DBusGTypeSpecializedMapVtable *)(data->klass->vtable); +} + +const DBusGTypeSpecializedCollectionVtable* dbus_g_type_collection_peek_vtable (GType collection_type) +{ + DBusGTypeSpecializedData *data; + g_return_val_if_fail (dbus_g_type_is_collection(collection_type), NULL); + + data = lookup_specialization_data (collection_type); + g_assert (data != NULL); + + return (DBusGTypeSpecializedCollectionVtable *)(data->klass->vtable); +} + + static GType register_specialized_instance (const DBusGTypeSpecializedContainer *klass, char *name, diff --git a/glib/dbus-gtype-specialized.h b/glib/dbus-gtype-specialized.h index e95af3e5..505c95bc 100644 --- a/glib/dbus-gtype-specialized.h +++ b/glib/dbus-gtype-specialized.h @@ -89,7 +89,7 @@ typedef struct { DBusGTypeSpecializedConstructor constructor; DBusGTypeSpecializedFreeFunc free_func; DBusGTypeSpecializedCopyFunc copy_func; - gpointer padding1; + GDestroyNotify simple_free_func; /* for type-independent freeing if possible */ gpointer padding2; gpointer padding3; } DBusGTypeSpecializedVtable; @@ -125,6 +125,8 @@ void dbus_g_type_register_collection (const char void dbus_g_type_register_map (const char *name, const DBusGTypeSpecializedMapVtable *vtable, guint flags); +const DBusGTypeSpecializedMapVtable* dbus_g_type_map_peek_vtable (GType map_type); +const DBusGTypeSpecializedCollectionVtable* dbus_g_type_collection_peek_vtable (GType collection_type); G_END_DECLS diff --git a/glib/dbus-gvalue-utils.c b/glib/dbus-gvalue-utils.c index 4956f222..04c0c3e8 100644 --- a/glib/dbus-gvalue-utils.c +++ b/glib/dbus-gvalue-utils.c @@ -311,10 +311,29 @@ hash_free_from_gtype (GType gtype, GDestroyNotify *func) } else if (gtype == G_TYPE_VALUE_ARRAY) { - *func = g_value_array_free; - return TRUE; + *func = (GDestroyNotify) g_value_array_free; + return TRUE; + } + else if (dbus_g_type_is_collection (gtype)) + { + const DBusGTypeSpecializedCollectionVtable* vtable; + vtable = dbus_g_type_collection_peek_vtable (gtype); + if (vtable->base_vtable.simple_free_func) + { + *func = vtable->base_vtable.simple_free_func; + return TRUE; + } + } + else if (dbus_g_type_is_map (gtype)) + { + const DBusGTypeSpecializedMapVtable* vtable; + vtable = dbus_g_type_map_peek_vtable (gtype); + if (vtable->base_vtable.simple_free_func) + { + *func = vtable->base_vtable.simple_free_func; + return TRUE; + } } - return FALSE; } } @@ -587,7 +606,7 @@ hashtable_copy (GType type, gpointer src) } static void -hashtable_free (GType type, gpointer val) +hashtable_simple_free (gpointer val) { g_hash_table_destroy (val); } @@ -629,7 +648,7 @@ array_copy (GType type, gpointer src) } static void -array_free (GType type, gpointer val) +array_simple_free (gpointer val) { GArray *array; array = val; @@ -768,6 +787,7 @@ ptrarray_append (DBusGTypeSpecializedAppendContext *ctx, GValue *value) static void ptrarray_free (GType type, gpointer val) { + /* XXX: this function appears to leak the contents of the array */ GPtrArray *array; array = val; g_ptr_array_free (array, TRUE); @@ -852,6 +872,7 @@ slist_end_append (DBusGTypeSpecializedAppendContext *ctx) static void slist_free (GType type, gpointer val) { + /* XXX: this function appears to leak the contents of the list */ GSList *list; list = val; g_slist_free (list); @@ -860,11 +881,18 @@ slist_free (GType type, gpointer val) void _dbus_g_type_specialized_builtins_init (void) { + /* types with a simple_free function can be freed at run-time without + * the destroy function needing to know the type, so they can be + * stored in hash tables */ + static const DBusGTypeSpecializedCollectionVtable array_vtable = { { array_constructor, - array_free, + NULL, array_copy, + array_simple_free, + NULL, + NULL, }, array_fixed_accessor, NULL, @@ -878,6 +906,9 @@ _dbus_g_type_specialized_builtins_init (void) ptrarray_constructor, ptrarray_free, ptrarray_copy, + NULL, + NULL, + NULL, }, NULL, ptrarray_iterator, @@ -891,6 +922,9 @@ _dbus_g_type_specialized_builtins_init (void) slist_constructor, slist_free, slist_copy, + NULL, + NULL, + NULL, }, NULL, slist_iterator, @@ -901,9 +935,9 @@ _dbus_g_type_specialized_builtins_init (void) static const DBusGTypeSpecializedMapVtable hashtable_vtable = { { hashtable_constructor, - hashtable_free, - hashtable_copy, NULL, + hashtable_copy, + hashtable_simple_free, NULL, NULL }, -- cgit