[glib] binding: Add an explicit unbind()
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] binding: Add an explicit unbind()
- Date: Thu, 2 May 2013 22:51:34 +0000 (UTC)
commit a360b314aad5dcbc575948a401d22d47a36e4328
Author: Emmanuele Bassi <ebassi gnome org>
Date: Sun Apr 14 21:04:41 2013 +0100
binding: Add an explicit unbind()
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 | 89 ++++++++++++++++++---------
gobject/gbinding.h | 2 +
gobject/tests/binding.c | 32 ++++++++++
4 files changed, 95 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..714bb1c 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_unbind() 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_unbind (binding);
G_OBJECT_CLASS (g_binding_parent_class)->finalize (gobject);
}
@@ -772,6 +753,56 @@ g_binding_get_target_property (GBinding *binding)
}
/**
+ * g_binding_unbind:
+ * @binding: a #GBinding
+ *
+ * Explicitly releases the binding between the source and the target
+ * property expressed by @binding.
+ *
+ * This function does not change the reference count of @binding.
+ *
+ * Since: 2.38
+ */
+void
+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_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..e49ad6d 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_unbind (GBinding *binding);
GLIB_AVAILABLE_IN_ALL
GBinding *g_object_bind_property (gpointer source,
diff --git a/gobject/tests/binding.c b/gobject/tests/binding.c
index b6dcdbb..7f7121e 100644
--- a/gobject/tests/binding.c
+++ b/gobject/tests/binding.c
@@ -570,6 +570,37 @@ binding_same_object (void)
g_object_unref (source);
}
+static void
+binding_unbind (void)
+{
+ BindingSource *source = g_object_new (binding_source_get_type (), NULL);
+ BindingTarget *target = g_object_new (binding_target_get_type (), NULL);
+ GBinding *binding;
+
+ binding = g_object_bind_property (source, "foo",
+ target, "bar",
+ G_BINDING_DEFAULT);
+ g_object_add_weak_pointer (G_OBJECT (binding), (gpointer *) &binding);
+
+
+ g_object_set (source, "foo", 42, NULL);
+ g_assert_cmpint (source->foo, ==, target->bar);
+
+ g_object_set (target, "bar", 47, NULL);
+ g_assert_cmpint (source->foo, !=, target->bar);
+
+ g_binding_unbind (binding);
+ 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
main (int argc, char *argv[])
{
@@ -586,6 +617,7 @@ main (int argc, char *argv[])
g_test_add_func ("/binding/sync-create", binding_sync_create);
g_test_add_func ("/binding/invert-boolean", binding_invert_boolean);
g_test_add_func ("/binding/same-object", binding_same_object);
+ g_test_add_func ("/binding/unbind", binding_unbind);
return g_test_run ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]