mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-11 23:16:14 +01:00
gobject: Do not call toggle down notifications if current refcount is not 1
When an object is revitalized and a notify callbacks increased the reference counter of the object, we are calling the toggle notifier twice, while it should only happen if also the actual reference count value is 1 (after having been decremented from 2).
This commit is contained in:
parent
1f852863ec
commit
0918ce013a
@ -3891,7 +3891,8 @@ g_object_unref (gpointer _object)
|
|||||||
TRACE (GOBJECT_OBJECT_UNREF(object,G_TYPE_FROM_INSTANCE(object),old_ref));
|
TRACE (GOBJECT_OBJECT_UNREF(object,G_TYPE_FROM_INSTANCE(object),old_ref));
|
||||||
|
|
||||||
/* if we went from 2->1 we need to notify toggle refs if any */
|
/* if we went from 2->1 we need to notify toggle refs if any */
|
||||||
if (old_ref == 2 && OBJECT_HAS_TOGGLE_REF (object))
|
if (old_ref == 2 && OBJECT_HAS_TOGGLE_REF (object) &&
|
||||||
|
g_atomic_int_get ((int *)&object->ref_count) == 1)
|
||||||
{
|
{
|
||||||
/* The last ref being held in this case is owned by the toggle_ref */
|
/* The last ref being held in this case is owned by the toggle_ref */
|
||||||
toggle_refs_notify (object, TRUE);
|
toggle_refs_notify (object, TRUE);
|
||||||
|
@ -731,6 +731,11 @@ toggle_notify (gpointer data,
|
|||||||
|
|
||||||
g_assert (is_last == c->should_be_last);
|
g_assert (is_last == c->should_be_last);
|
||||||
|
|
||||||
|
if (is_last)
|
||||||
|
g_assert_cmpint (g_atomic_int_get (&obj->ref_count), ==, 1);
|
||||||
|
else
|
||||||
|
g_assert_cmpint (g_atomic_int_get (&obj->ref_count), ==, 2);
|
||||||
|
|
||||||
c->count++;
|
c->count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1021,6 +1026,11 @@ toggle_notify_counter (gpointer data,
|
|||||||
{
|
{
|
||||||
Count *c = data;
|
Count *c = data;
|
||||||
c->count++;
|
c->count++;
|
||||||
|
|
||||||
|
if (is_last)
|
||||||
|
g_assert_cmpint (g_atomic_int_get (&obj->ref_count), ==, 1);
|
||||||
|
else
|
||||||
|
g_assert_cmpint (g_atomic_int_get (&obj->ref_count), ==, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1049,6 +1059,20 @@ on_object_notify_switch_to_toggle_ref (GObject *object,
|
|||||||
g_object_unref (object);
|
g_object_unref (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_object_notify_add_ref (GObject *object,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
DisposeReffingObject *obj = DISPOSE_REFFING_OBJECT (object);
|
||||||
|
int old_toggle_cout = obj->actual.count;
|
||||||
|
|
||||||
|
obj->notify_called++;
|
||||||
|
|
||||||
|
g_object_ref (object);
|
||||||
|
g_assert_cmpint (obj->actual.count, ==, old_toggle_cout);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_toggle_ref_and_notify_on_dispose (void)
|
test_toggle_ref_and_notify_on_dispose (void)
|
||||||
{
|
{
|
||||||
@ -1116,8 +1140,23 @@ test_toggle_ref_and_notify_on_dispose (void)
|
|||||||
disposed_checker = &obj;
|
disposed_checker = &obj;
|
||||||
g_object_add_weak_pointer (G_OBJECT (obj), &disposed_checker);
|
g_object_add_weak_pointer (G_OBJECT (obj), &disposed_checker);
|
||||||
|
|
||||||
obj->disposing_refs = 0;
|
/* Check that notification is triggered after being queued, but that toggle
|
||||||
|
* is not happening if current refcount changed.
|
||||||
|
*/
|
||||||
|
obj->disposing_refs = 1;
|
||||||
|
obj->disposing_refs_all_normal = FALSE;
|
||||||
obj->expected.count = 7;
|
obj->expected.count = 7;
|
||||||
|
obj->notify_handler = G_CALLBACK (on_object_notify_add_ref);
|
||||||
|
g_object_remove_toggle_ref (G_OBJECT (obj), obj->toggle_notify, NULL);
|
||||||
|
g_assert_cmpint (obj->actual.count, ==, 8);
|
||||||
|
g_assert_cmpuint (obj->notify_called, ==, 4);
|
||||||
|
g_object_unref (obj);
|
||||||
|
|
||||||
|
disposed_checker = &obj;
|
||||||
|
g_object_add_weak_pointer (G_OBJECT (obj), &disposed_checker);
|
||||||
|
|
||||||
|
obj->disposing_refs = 0;
|
||||||
|
obj->expected.count = 9;
|
||||||
g_clear_object (&obj);
|
g_clear_object (&obj);
|
||||||
g_assert_null (disposed_checker);
|
g_assert_null (disposed_checker);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user