[glib/wip/gproperty-2: 1/7] binding: Add an explicit release()



commit 5c51ad64a2b781354905f707cb7d17833e7717e6
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Sun Apr 14 21:04:41 2013 +0100

    binding: Add an explicit release()
    
    Higher order languages with garbage collection can have issues releasing
    a binding, as they do not control the last reference being dropped on
    the binding, source, or target instances.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=698018

 docs/reference/gobject/gobject-sections.txt |    1 +
 gobject/gbinding.c                          |   93 ++++++++++++++++++--------
 gobject/gbinding.h                          |    2 +
 3 files changed, 67 insertions(+), 29 deletions(-)
---
diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt
index d507f15..56d0e22 100644
--- a/docs/reference/gobject/gobject-sections.txt
+++ b/docs/reference/gobject/gobject-sections.txt
@@ -935,6 +935,7 @@ g_binding_get_source_property
 g_binding_get_target
 g_binding_get_target_property
 g_binding_get_flags
+g_binding_release
 <SUBSECTION>
 g_object_bind_property
 GBindingTransformFunc
diff --git a/gobject/gbinding.c b/gobject/gbinding.c
index 3dbe616..645d60e 100644
--- a/gobject/gbinding.c
+++ b/gobject/gbinding.c
@@ -96,6 +96,11 @@
  * either one of the #GObject instances it refers to are finalized, or when
  * the #GBinding instance loses its last reference.
  *
+ * <note><para>Bindings for languages with garbage collection can use
+ * g_binding_release() to explicitly release a binding between the source
+ * and target properties, instead of relying on the last reference on the
+ * binding, source, and target instances to drop.</para></note>
+ *
  * #GBinding is available since GObject 2.26
  */
 
@@ -244,6 +249,8 @@ weak_unbind (gpointer  user_data,
 
       g_object_weak_unref (binding->source, weak_unbind, user_data);
       remove_binding_qdata (binding->source, binding);
+
+      binding->source_notify = 0;
       binding->source = NULL;
     }
 
@@ -257,6 +264,8 @@ weak_unbind (gpointer  user_data,
 
       g_object_weak_unref (binding->target, weak_unbind, user_data);
       remove_binding_qdata (binding->target, binding);
+
+      binding->target_notify = 0;
       binding->target = NULL;
     }
 
@@ -431,35 +440,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);
-
-      binding->transform_data = 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_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);
-    }
-
-  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);
-    }
+  g_binding_release (binding);
 
   G_OBJECT_CLASS (g_binding_parent_class)->finalize (gobject);
 }
@@ -772,6 +753,60 @@ g_binding_get_target_property (GBinding *binding)
 }
 
 /**
+ * g_binding_release:
+ * @binding: a #GBinding
+ *
+ * Releases the binding between the source and the target property.
+ *
+ * This function does not change the reference count of @binding.
+ *
+ * This function is meant for language bindings.
+ *
+ * Since: 2.38
+ */
+void
+g_binding_release (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;
+    }
+
+  /* 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)
+        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_object_bind_property_full:
  * @source: (type GObject.Object): the source #GObject
  * @source_property: the property on @source to bind
diff --git a/gobject/gbinding.h b/gobject/gbinding.h
index ebb329c..0625b01 100644
--- a/gobject/gbinding.h
+++ b/gobject/gbinding.h
@@ -115,6 +115,8 @@ GLIB_AVAILABLE_IN_ALL
 const gchar *         g_binding_get_source_property (GBinding *binding);
 GLIB_AVAILABLE_IN_ALL
 const gchar *         g_binding_get_target_property (GBinding *binding);
+GLIB_AVAILABLE_IN_2_38
+void                  g_binding_release             (GBinding *binding);
 
 GLIB_AVAILABLE_IN_ALL
 GBinding *g_object_bind_property               (gpointer               source,


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