mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-11-01 17:02:18 +01:00
gobject: preserve order of weak notifications in g_object_weak_unref()
g_object_weak_unref() would have done a fast-removal of the entry, which messes up the order of the weak notifications. During destruction of the object we emit the weak notifications. They are emitted in the order in which they were registered (FIFO). Except, when a g_object_weak_unref() messes up the order. Avoid that and preserve the order. Now, do a memmove(), which is O(n). But note that we already track weak references in a flat array that requires a O(n) linear search. Thus, g_object_weak_unref() was already O(n) and that didn't change. More importantly, users are well advised to limit themselves to a reasonably small number of weak notifications. And for small n, the linear search and the memmove() is an efficient solution.
This commit is contained in:
committed by
Michael Catanzaro
parent
7743c7aaa2
commit
d2e08b7dfe
@@ -3827,7 +3827,11 @@ g_object_weak_unref_cb (gpointer *data,
|
||||
*data = NULL;
|
||||
}
|
||||
else if (i != wstack->n_weak_refs)
|
||||
wstack->weak_refs[i] = wstack->weak_refs[wstack->n_weak_refs];
|
||||
{
|
||||
memmove (&wstack->weak_refs[i],
|
||||
&wstack->weak_refs[i + 1],
|
||||
sizeof (wstack->weak_refs[i]) * (wstack->n_weak_refs - i));
|
||||
}
|
||||
|
||||
found_one = TRUE;
|
||||
break;
|
||||
|
||||
@@ -285,7 +285,6 @@ test_references (void)
|
||||
/*****************************************************************************/
|
||||
|
||||
static guint weak_ref4_notified;
|
||||
static guint weak_ref4_has_stable_order;
|
||||
|
||||
static void
|
||||
weak_ref4 (gpointer data,
|
||||
@@ -294,12 +293,9 @@ weak_ref4 (gpointer data,
|
||||
static gint last = -1;
|
||||
gint idx;
|
||||
|
||||
if (weak_ref4_has_stable_order)
|
||||
{
|
||||
idx = (gint) GPOINTER_TO_UINT (data);
|
||||
g_assert_cmpint (last, <, idx);
|
||||
last = idx;
|
||||
}
|
||||
idx = (gint) GPOINTER_TO_UINT (data);
|
||||
g_assert_cmpint (last, <, idx);
|
||||
last = idx;
|
||||
|
||||
weak_ref4_notified++;
|
||||
}
|
||||
@@ -331,17 +327,9 @@ test_references_many (void)
|
||||
indexes[i] = indexes[j];
|
||||
indexes[j] = tmp;
|
||||
}
|
||||
if (g_random_boolean ())
|
||||
{
|
||||
m = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m = g_random_int () % (n + 1u);
|
||||
for (i = 0; i < m; i++)
|
||||
g_object_weak_unref (object, weak_ref4, GUINT_TO_POINTER (indexes[i]));
|
||||
}
|
||||
weak_ref4_has_stable_order = (m == 0);
|
||||
m = g_random_int () % (n + 1u);
|
||||
for (i = 0; i < m; i++)
|
||||
g_object_weak_unref (object, weak_ref4, GUINT_TO_POINTER (indexes[i]));
|
||||
g_object_unref (object);
|
||||
g_assert_cmpint (weak_ref4_notified, ==, n - m);
|
||||
g_free (indexes);
|
||||
|
||||
Reference in New Issue
Block a user