gobject: rework g_object_notify_queue_freeze() to use g_datalist_id_update_atomic()

A common pattern is to look whether a GData entry exists, and if it
doesn't, add it.

For that, we currently always must take a OPTIONAL_BIT_LOCK_NOTIFY lock.

This can be avoided, because GData already uses an internal mutex. By
using g_datalist_id_update_atomic(), we can perform all relevant
operations while holding that mutex.

Move functionality from g_object_notify_queue_freeze() inside
g_datalist_id_update_atomic().

The goal will be to drop the OPTIONAL_BIT_LOCK_NOTIFY lock in a later
commit.
This commit is contained in:
Thomas Haller 2024-01-19 11:38:40 +01:00
parent 0564abf6e0
commit 56dc2a390b

View File

@ -667,18 +667,45 @@ g_object_notify_queue_free (gpointer data)
}
static GObjectNotifyQueue *
g_object_notify_queue_create_queue_frozen (GObject *object)
g_object_notify_queue_new_frozen (void)
{
GObjectNotifyQueue *nqueue;
nqueue = g_new0 (GObjectNotifyQueue, 1);
nqueue = g_new (GObjectNotifyQueue, 1);
*nqueue = (GObjectNotifyQueue){
.freeze_count = 1,
};
g_datalist_id_set_data_full (&object->qdata, quark_notify_queue,
nqueue, g_object_notify_queue_free);
return nqueue;
}
static gpointer
g_object_notify_queue_freeze_cb (gpointer *data,
GDestroyNotify *destroy_notify,
gpointer user_data)
{
GObject *object = user_data;
GObjectNotifyQueue *nqueue = *data;
if (!nqueue)
{
/* The nqueue doesn't exist yet. We create it, and freeze thus 1 time. */
nqueue = g_object_notify_queue_new_frozen ();
*data = nqueue;
*destroy_notify = g_object_notify_queue_free;
}
else
{
if (nqueue->freeze_count >= 65535)
{
g_critical ("Free queue for %s (%p) is larger than 65535,"
" called g_object_freeze_notify() too often."
" Forgot to call g_object_thaw_notify() or infinite loop",
G_OBJECT_TYPE_NAME (object), object);
}
else
nqueue->freeze_count++;
}
return nqueue;
}
@ -689,24 +716,11 @@ g_object_notify_queue_freeze (GObject *object)
GObjectNotifyQueue *nqueue;
object_bit_lock (object, OPTIONAL_BIT_LOCK_NOTIFY);
nqueue = g_datalist_id_get_data (&object->qdata, quark_notify_queue);
if (!nqueue)
{
nqueue = g_object_notify_queue_create_queue_frozen (object);
goto out;
}
if (nqueue->freeze_count >= 65535)
g_critical("Free queue for %s (%p) is larger than 65535,"
" called g_object_freeze_notify() too often."
" Forgot to call g_object_thaw_notify() or infinite loop",
G_OBJECT_TYPE_NAME (object), object);
else
nqueue->freeze_count++;
out:
nqueue = _g_datalist_id_update_atomic (&object->qdata,
quark_notify_queue,
g_object_notify_queue_freeze_cb,
object);
object_bit_unlock (object, OPTIONAL_BIT_LOCK_NOTIFY);
return nqueue;
}
@ -797,7 +811,9 @@ g_object_notify_queue_add (GObject *object,
* Note that this freeze will be balanced at the end of object
* initialization.
*/
nqueue = g_object_notify_queue_create_queue_frozen (object);
nqueue = g_object_notify_queue_new_frozen ();
g_datalist_id_set_data_full (&object->qdata, quark_notify_queue,
nqueue, g_object_notify_queue_free);
}
}