mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +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));
|
||||
|
||||
/* 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 */
|
||||
toggle_refs_notify (object, TRUE);
|
||||
|
@ -731,6 +731,11 @@ toggle_notify (gpointer data,
|
||||
|
||||
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++;
|
||||
}
|
||||
|
||||
@ -1021,6 +1026,11 @@ toggle_notify_counter (gpointer data,
|
||||
{
|
||||
Count *c = data;
|
||||
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
|
||||
@ -1049,6 +1059,20 @@ on_object_notify_switch_to_toggle_ref (GObject *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
|
||||
test_toggle_ref_and_notify_on_dispose (void)
|
||||
{
|
||||
@ -1116,8 +1140,23 @@ test_toggle_ref_and_notify_on_dispose (void)
|
||||
disposed_checker = &obj;
|
||||
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->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_assert_null (disposed_checker);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user