mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-10-31 16:32:18 +01:00 
			
		
		
		
	binding: Use a hash table
Since an object instance might have a lot of bindings, using a list might become a performance issue when removing them. Using a simple hash table guarantees constant time lookup, which is the most common operation.
This commit is contained in:
		| @@ -194,34 +194,45 @@ static inline void | |||||||
| add_binding_qdata (GObject  *gobject, | add_binding_qdata (GObject  *gobject, | ||||||
|                    GBinding *binding) |                    GBinding *binding) | ||||||
| { | { | ||||||
|   GList *bindings; |   GHashTable *bindings; | ||||||
|  |  | ||||||
|   bindings = g_object_get_qdata (gobject, quark_gbinding); |   bindings = g_object_get_qdata (gobject, quark_gbinding); | ||||||
|   if (bindings == NULL) |   if (bindings == NULL) | ||||||
|     { |     { | ||||||
|       bindings = g_list_prepend (NULL, binding); |       bindings = g_hash_table_new (NULL, NULL); | ||||||
|       g_object_set_qdata (gobject, quark_gbinding, bindings); |  | ||||||
|  |       g_object_set_qdata_full (gobject, quark_gbinding, | ||||||
|  |                                bindings, | ||||||
|  |                                (GDestroyNotify) g_hash_table_destroy); | ||||||
|     } |     } | ||||||
|   else |  | ||||||
|     bindings = g_list_prepend (bindings, binding); |   g_hash_table_insert (bindings, binding, GUINT_TO_POINTER (1)); | ||||||
| } | } | ||||||
|  |  | ||||||
| static inline void | static inline void | ||||||
| remove_binding_qdata (GObject  *gobject, | remove_binding_qdata (GObject  *gobject, | ||||||
|                       GBinding *binding) |                       GBinding *binding) | ||||||
| { | { | ||||||
|   GList *bindings; |   GHashTable *bindings; | ||||||
|  |  | ||||||
|   bindings = g_object_get_qdata (gobject, quark_gbinding); |   bindings = g_object_get_qdata (gobject, quark_gbinding); | ||||||
|   bindings = g_list_remove (bindings, binding); |   g_hash_table_remove (bindings, binding); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* the basic assumption is that if either the source or the target | ||||||
|  |  * goes away then the binding does not exist any more and it should | ||||||
|  |  * be reaped as well | ||||||
|  |  */ | ||||||
| static void | static void | ||||||
| weak_unbind (gpointer  user_data, | weak_unbind (gpointer  user_data, | ||||||
|              GObject  *where_the_object_was) |              GObject  *where_the_object_was) | ||||||
| { | { | ||||||
|   GBinding *binding = user_data; |   GBinding *binding = user_data; | ||||||
|  |  | ||||||
|  |   /* if what went away was the source, unset it so that GBinding::finalize | ||||||
|  |    * does not try to access it; otherwise, disconnect everything and remove | ||||||
|  |    * the GBinding instance from the object's qdata | ||||||
|  |    */ | ||||||
|   if (binding->source == where_the_object_was) |   if (binding->source == where_the_object_was) | ||||||
|     binding->source = NULL; |     binding->source = NULL; | ||||||
|   else |   else | ||||||
| @@ -234,6 +245,7 @@ weak_unbind (gpointer  user_data, | |||||||
|       binding->source = NULL; |       binding->source = NULL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |   /* as above, but with the target */ | ||||||
|   if (binding->target == where_the_object_was) |   if (binding->target == where_the_object_was) | ||||||
|     binding->target = NULL; |     binding->target = NULL; | ||||||
|   else |   else | ||||||
| @@ -246,6 +258,7 @@ weak_unbind (gpointer  user_data, | |||||||
|       binding->target = NULL; |       binding->target = NULL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |   /* this will take care of the binding itself */ | ||||||
|   g_object_unref (binding); |   g_object_unref (binding); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -399,6 +412,7 @@ g_binding_finalize (GObject *gobject) | |||||||
| { | { | ||||||
|   GBinding *binding = G_BINDING (gobject); |   GBinding *binding = G_BINDING (gobject); | ||||||
|  |  | ||||||
|  |   /* dispose of the transformation data */ | ||||||
|   if (binding->notify != NULL) |   if (binding->notify != NULL) | ||||||
|     { |     { | ||||||
|       binding->notify (binding->transform_data); |       binding->notify (binding->transform_data); | ||||||
| @@ -407,6 +421,9 @@ g_binding_finalize (GObject *gobject) | |||||||
|       binding->notify = NULL; |       binding->notify = NULL; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |   /* we need this in case the source and target instance are still | ||||||
|  |    * valid, and it was the GBinding that was unreferenced | ||||||
|  |    */ | ||||||
|   if (binding->source != NULL) |   if (binding->source != NULL) | ||||||
|     { |     { | ||||||
|       if (binding->source_notify != 0) |       if (binding->source_notify != 0) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user