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
This commit is contained in:
Emmanuele Bassi 2013-05-16 22:28:54 +01:00
parent 270d73a1e0
commit 25a3c8720c
2 changed files with 48 additions and 37 deletions

View File

@ -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);
}
/**

View File

@ -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