gobject: Check for toggle references only if the old ref is relevant

If an object gets revitalized during the dispose vfunc, we need to call
toggle refs notifiers only if we had 2 references and if the object has
the toggle references enabled.

This may change in case an object notifier handler changes this status,
so do this check only after we've called the notifiers so that in case
toggle notifications are enabled afterwards we still call the handlers.
This commit is contained in:
Marco Trevisan (Treviño) 2022-12-06 04:07:54 +01:00
parent 5e2b288033
commit 1f852863ec
2 changed files with 7 additions and 5 deletions

View File

@ -3879,7 +3879,6 @@ g_object_unref (gpointer _object)
while (old_ref > 1)
{
/* valid if last 2 refs are owned by this call to unref and the toggle_ref */
gboolean has_toggle_ref = OBJECT_HAS_TOGGLE_REF (object);
if (!g_atomic_int_compare_and_exchange_full ((int *)&object->ref_count,
old_ref, old_ref - 1,
@ -3892,8 +3891,11 @@ g_object_unref (gpointer _object)
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 (old_ref == 2 && has_toggle_ref) /* The last ref being held in this case is owned by the toggle_ref */
toggle_refs_notify (object, TRUE);
if (old_ref == 2 && OBJECT_HAS_TOGGLE_REF (object))
{
/* The last ref being held in this case is owned by the toggle_ref */
toggle_refs_notify (object, TRUE);
}
return;
}

View File

@ -1110,14 +1110,14 @@ test_toggle_ref_and_notify_on_dispose (void)
obj->expected.count = 5;
obj->notify_handler = G_CALLBACK (on_object_notify_switch_to_toggle_ref);
g_object_unref (obj);
g_assert_cmpint (obj->actual.count, ==, 6);
g_assert_cmpint (obj->actual.count, ==, 7);
g_assert_cmpuint (obj->notify_called, ==, 3);
disposed_checker = &obj;
g_object_add_weak_pointer (G_OBJECT (obj), &disposed_checker);
obj->disposing_refs = 0;
obj->expected.count = 6;
obj->expected.count = 7;
g_clear_object (&obj);
g_assert_null (disposed_checker);
}