gobject: rework g_object_notify_queue_thaw() to use g_datalist_id_update_atomic()

The goal is to drop OPTIONAL_BIT_LOCK_NOTIFY lock. This is one step.
Move code inside g_datalist_id_update_atomic().
This commit is contained in:
Thomas Haller 2024-01-28 12:56:47 +01:00
parent 626b6518b3
commit 5d81e243d4

View File

@ -724,51 +724,75 @@ g_object_notify_queue_freeze (GObject *object)
return nqueue;
}
static gpointer
g_object_notify_queue_thaw_cb (gpointer *data,
GDestroyNotify *destroy_notify,
gpointer user_data)
{
GObject *object = ((gpointer *) user_data)[0];
GObjectNotifyQueue *nqueue0 = ((gpointer *) user_data)[1];
GObjectNotifyQueue *nqueue = *data;
#if G_ENABLE_DEBUG
g_assert (!nqueue0 || nqueue0 == nqueue);
#endif
(void) nqueue0;
if (G_UNLIKELY (!nqueue || nqueue->freeze_count == 0))
{
g_critical ("%s: property-changed notification for %s(%p) is not frozen",
G_STRFUNC, G_OBJECT_TYPE_NAME (object), object);
return NULL;
}
nqueue->freeze_count--;
if (nqueue->freeze_count > 0)
return NULL;
*data = NULL;
return nqueue;
}
static void
g_object_notify_queue_thaw (GObject *object,
GObjectNotifyQueue *nqueue,
gboolean take_ref)
{
GParamSpec *pspecs_mem[16], **pspecs, **free_me = NULL;
GParamSpec *pspecs_stack[16];
GParamSpec **pspecs_heap = NULL;
GParamSpec **pspecs = pspecs_stack;
guint n_pspecs;
GSList *slist;
guint n_pspecs = 0;
object_bit_lock (object, OPTIONAL_BIT_LOCK_NOTIFY);
nqueue = _g_datalist_id_update_atomic (&object->qdata,
quark_notify_queue,
g_object_notify_queue_thaw_cb,
((gpointer[]){ object, nqueue }));
object_bit_unlock (object, OPTIONAL_BIT_LOCK_NOTIFY);
if (!nqueue)
{
/* Caller didn't look up the queue yet. Do it now. */
nqueue = g_datalist_id_get_data (&object->qdata, quark_notify_queue);
}
/* Just make sure we never get into some nasty race condition */
if (G_UNLIKELY (!nqueue || nqueue->freeze_count == 0))
{
object_bit_unlock (object, OPTIONAL_BIT_LOCK_NOTIFY);
g_critical ("%s: property-changed notification for %s(%p) is not frozen",
G_STRFUNC, G_OBJECT_TYPE_NAME (object), object);
return;
}
nqueue->freeze_count--;
if (nqueue->freeze_count)
if (nqueue->n_pspecs == 0)
goto out;
if (nqueue->n_pspecs > G_N_ELEMENTS (pspecs_stack))
{
object_bit_unlock (object, OPTIONAL_BIT_LOCK_NOTIFY);
return;
pspecs_heap = g_new (GParamSpec *, nqueue->n_pspecs);
pspecs = pspecs_heap;
}
pspecs = nqueue->n_pspecs > 16 ? free_me = g_new (GParamSpec*, nqueue->n_pspecs) : pspecs_mem;
n_pspecs = 0;
for (slist = nqueue->pspecs; slist; slist = slist->next)
{
pspecs[n_pspecs++] = slist->data;
}
g_datalist_id_set_data (&object->qdata, quark_notify_queue, NULL);
#if G_ENABLE_DEBUG
g_assert (n_pspecs == nqueue->n_pspecs);
#endif
object_bit_unlock (object, OPTIONAL_BIT_LOCK_NOTIFY);
if (n_pspecs)
{
if (take_ref)
g_object_ref (object);
@ -776,8 +800,12 @@ g_object_notify_queue_thaw (GObject *object,
if (take_ref)
g_object_unref (object);
}
g_free (free_me);
if (pspecs_heap)
g_free (pspecs_heap);
out:
g_object_notify_queue_free (nqueue);
}
static gboolean