summaryrefslogtreecommitdiff
path: root/gobject/gbinding.c
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@linux.intel.com>2010-06-16 15:08:10 +0100
committerEmmanuele Bassi <ebassi@linux.intel.com>2010-06-16 15:08:10 +0100
commit33aa4b4c662f18433ed27cd319ab5c97e5a9d9da (patch)
treeb9d4eadc4d6bdcce56f387a2a9ebd71ce816280d /gobject/gbinding.c
parentf72f65643fb1d832e8296b26cff77dedbdac310f (diff)
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.
Diffstat (limited to 'gobject/gbinding.c')
-rw-r--r--gobject/gbinding.c31
1 files changed, 24 insertions, 7 deletions
diff --git a/gobject/gbinding.c b/gobject/gbinding.c
index 200d72ff8..628ede942 100644
--- a/gobject/gbinding.c
+++ b/gobject/gbinding.c
@@ -194,34 +194,45 @@ static inline void
add_binding_qdata (GObject *gobject,
GBinding *binding)
{
- GList *bindings;
+ GHashTable *bindings;
bindings = g_object_get_qdata (gobject, quark_gbinding);
if (bindings == NULL)
{
- bindings = g_list_prepend (NULL, binding);
- g_object_set_qdata (gobject, quark_gbinding, bindings);
+ bindings = g_hash_table_new (NULL, NULL);
+
+ 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
remove_binding_qdata (GObject *gobject,
GBinding *binding)
{
- GList *bindings;
+ GHashTable *bindings;
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
weak_unbind (gpointer user_data,
GObject *where_the_object_was)
{
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)
binding->source = NULL;
else
@@ -234,6 +245,7 @@ weak_unbind (gpointer user_data,
binding->source = NULL;
}
+ /* as above, but with the target */
if (binding->target == where_the_object_was)
binding->target = NULL;
else
@@ -246,6 +258,7 @@ weak_unbind (gpointer user_data,
binding->target = NULL;
}
+ /* this will take care of the binding itself */
g_object_unref (binding);
}
@@ -399,6 +412,7 @@ g_binding_finalize (GObject *gobject)
{
GBinding *binding = G_BINDING (gobject);
+ /* dispose of the transformation data */
if (binding->notify != NULL)
{
binding->notify (binding->transform_data);
@@ -407,6 +421,9 @@ g_binding_finalize (GObject *gobject)
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_notify != 0)