[glib/wip/gproperty-2: 161/178] binding: Make unbind() release the reference on GBinding



commit 1ae23b180009f8a7ed1b49a05596c4e5fbed65b0
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Thu May 16 22:28:54 2013 +0100

    binding: Make unbind() release the reference on GBinding
    
    The automatic memory management of GBinding is not optimal for high
    order languages with garbage collectors semantics. If we leave the
    binding instance inert but still referenced it will be leaked, so one
    solution that does not throw away the baby of C convenience with the
    bathwater of language bindability is to have unbind() perform an
    implicit unref().
    
    Hopefully, C developers will read the documentation and especially the
    note that says that after calling unbind() the reference count on the
    GBinding instance is decreased.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=698018

 gobject/gbinding.c      |   81 +++++++++++++++++++++++++++-------------------
 gobject/tests/binding.c |    4 +--
 2 files changed, 48 insertions(+), 37 deletions(-)
---
diff --git a/gobject/gbinding.c b/gobject/gbinding.c
index 714bb1c..fd152b9 100644
--- a/gobject/gbinding.c
+++ b/gobject/gbinding.c
@@ -435,12 +435,53 @@ on_target_notify (GObject    *gobject,
   g_value_unset (&target_value);
 }
 
+static inline void
+g_binding_unbind_internal (GBinding *binding,
+                           gboolean  unref_binding)
+{
+  /* dispose of the transformation data */
+  if (binding->notify != NULL)
+    {
+      binding->notify (binding->transform_data);
+
+      binding->transform_data = NULL;
+      binding->notify = NULL;
+    }
+
+  if (binding->source != NULL)
+    {
+      if (binding->source_notify != 0)
+        g_signal_handler_disconnect (binding->source, binding->source_notify);
+
+      g_object_weak_unref (binding->source, weak_unbind, binding);
+      remove_binding_qdata (binding->source, binding);
+
+      binding->source_notify = 0;
+      binding->source = NULL;
+    }
+
+  if (binding->target != NULL)
+    {
+      if (binding->target_notify != 0)
+        g_signal_handler_disconnect (binding->target, binding->target_notify);
+
+      g_object_weak_unref (binding->target, weak_unbind, binding);
+      remove_binding_qdata (binding->target, binding);
+
+      binding->target_notify = 0;
+      binding->target = NULL;
+    }
+
+  if (unref_binding)
+    g_object_unref (binding);
+}
+
 static void
 g_binding_finalize (GObject *gobject)
 {
   GBinding *binding = G_BINDING (gobject);
 
-  g_binding_unbind (binding);
+  g_binding_unbind_internal (binding, FALSE);
 
   G_OBJECT_CLASS (g_binding_parent_class)->finalize (gobject);
 }
@@ -759,7 +800,10 @@ g_binding_get_target_property (GBinding *binding)
  * Explicitly releases the binding between the source and the target
  * property expressed by @binding.
  *
- * This function does not change the reference count of @binding.
+ * <note>This function will release the reference that is being held on
+ * the @binding instance; if you want to hold on to the #GBinding instance
+ * after calling g_binding_unbind(), you will need to hold a reference
+ * to it.</note>
  *
  * Since: 2.38
  */
@@ -768,38 +812,7 @@ g_binding_unbind (GBinding *binding)
 {
   g_return_if_fail (G_IS_BINDING (binding));
 
-  /* dispose of the transformation data */
-  if (binding->notify != NULL)
-    {
-      binding->notify (binding->transform_data);
-
-      binding->transform_data = NULL;
-      binding->notify = NULL;
-    }
-
-  if (binding->source != NULL)
-    {
-      if (binding->source_notify != 0)
-        g_signal_handler_disconnect (binding->source, binding->source_notify);
-
-      g_object_weak_unref (binding->source, weak_unbind, binding);
-      remove_binding_qdata (binding->source, binding);
-
-      binding->source_notify = 0;
-      binding->source = NULL;
-    }
-
-  if (binding->target != NULL)
-    {
-      if (binding->target_notify != 0)
-        g_signal_handler_disconnect (binding->target, binding->target_notify);
-
-      g_object_weak_unref (binding->target, weak_unbind, binding);
-      remove_binding_qdata (binding->target, binding);
-
-      binding->target_notify = 0;
-      binding->target = NULL;
-    }
+  g_binding_unbind_internal (binding, TRUE);
 }
 
 /**
diff --git a/gobject/tests/binding.c b/gobject/tests/binding.c
index 7f7121e..9eba7b5 100644
--- a/gobject/tests/binding.c
+++ b/gobject/tests/binding.c
@@ -590,15 +590,13 @@ binding_unbind (void)
   g_assert_cmpint (source->foo, !=, target->bar);
 
   g_binding_unbind (binding);
-  g_assert (binding != NULL);
+  g_assert (binding == NULL);
 
   g_object_set (source, "foo", 0, NULL);
   g_assert_cmpint (source->foo, !=, target->bar);
 
   g_object_unref (source);
   g_object_unref (target);
-  g_object_unref (binding);
-  g_assert (binding == NULL);
 }
 
 int


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]