mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-02 07:23:41 +02:00
Merge branch 'th/gobj-empty-notify-queue' into 'main'
[th/gobj-empty-notify-queue] gobject: optimize notify-queue handling for a single freeze See merge request GNOME/glib!4642
This commit is contained in:
@@ -599,6 +599,26 @@ weak_ref_data_has (GObject *object, WeakRefData *wrdata, WeakRefData **out_new_w
|
||||
|
||||
/* --- functions --- */
|
||||
|
||||
static const GObjectNotifyQueue notify_queue_empty = {
|
||||
.freeze_count = 0,
|
||||
};
|
||||
|
||||
G_ALWAYS_INLINE static inline gboolean
|
||||
_is_notify_queue_empty (const GObjectNotifyQueue *nqueue)
|
||||
{
|
||||
/* Only the notify_queue_empty instance has a zero freeze count. We check
|
||||
* here for that condition instead of pointer comparing to
|
||||
* ¬ify_queue_empty. That seems better because callers will afterwards
|
||||
* dereference "freeze_count", so the value is already loaded.
|
||||
*
|
||||
* In any case, both conditions must be equivalent.
|
||||
*/
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
g_assert ((nqueue == ¬ify_queue_empty) == (nqueue->freeze_count == 0));
|
||||
#endif
|
||||
return nqueue->freeze_count == 0;
|
||||
}
|
||||
|
||||
G_ALWAYS_INLINE static inline gsize
|
||||
g_object_notify_queue_alloc_size (gsize alloc)
|
||||
{
|
||||
@@ -630,9 +650,10 @@ g_object_notify_queue_freeze_cb (gpointer *data,
|
||||
|
||||
if (!nqueue)
|
||||
{
|
||||
/* The nqueue doesn't exist yet. We create it, and freeze thus 1 time. */
|
||||
*data = g_object_notify_queue_new_frozen ();
|
||||
*destroy_notify = g_free;
|
||||
/* The nqueue doesn't exist yet. We use the dummy object that is shared
|
||||
* by all instances. */
|
||||
*data = (gpointer) ¬ify_queue_empty;
|
||||
*destroy_notify = NULL;
|
||||
}
|
||||
else if (!freeze_always)
|
||||
{
|
||||
@@ -643,7 +664,14 @@ g_object_notify_queue_freeze_cb (gpointer *data,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (G_UNLIKELY (nqueue->freeze_count == G_MAXUINT16))
|
||||
if (_is_notify_queue_empty (nqueue))
|
||||
{
|
||||
nqueue = g_object_notify_queue_new_frozen ();
|
||||
*data = nqueue;
|
||||
*destroy_notify = g_free;
|
||||
nqueue->freeze_count++;
|
||||
}
|
||||
else if (G_UNLIKELY (nqueue->freeze_count == G_MAXUINT16))
|
||||
{
|
||||
g_critical ("Free queue for %s (%p) is larger than 65535,"
|
||||
" called g_object_freeze_notify() too often."
|
||||
@@ -674,19 +702,27 @@ g_object_notify_queue_thaw_cb (gpointer *data,
|
||||
GObject *object = user_data;
|
||||
GObjectNotifyQueue *nqueue = *data;
|
||||
|
||||
if (G_UNLIKELY (!nqueue || nqueue->freeze_count == 0))
|
||||
if (G_UNLIKELY (!nqueue))
|
||||
{
|
||||
g_critical ("%s: property-changed notification for %s(%p) is not frozen",
|
||||
G_STRFUNC, G_OBJECT_TYPE_NAME (object), object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (_is_notify_queue_empty (nqueue))
|
||||
{
|
||||
*data = NULL;
|
||||
*destroy_notify = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nqueue->freeze_count--;
|
||||
|
||||
if (nqueue->freeze_count > 0)
|
||||
return NULL;
|
||||
|
||||
*data = NULL;
|
||||
*destroy_notify = NULL;
|
||||
return nqueue;
|
||||
}
|
||||
|
||||
@@ -762,6 +798,12 @@ g_object_notify_queue_add_cb (gpointer *data,
|
||||
*data = nqueue;
|
||||
*destroy_notify = g_free;
|
||||
}
|
||||
else if (_is_notify_queue_empty (nqueue))
|
||||
{
|
||||
nqueue = g_object_notify_queue_new_frozen ();
|
||||
*data = nqueue;
|
||||
*destroy_notify = g_free;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < nqueue->len; i++)
|
||||
@@ -4479,6 +4521,7 @@ toggle_refs_unref_cb (gpointer *data,
|
||||
g_datalist_unset_flags (&trdata->object->qdata, OBJECT_HAS_TOGGLE_REF_FLAG);
|
||||
g_free (tstack);
|
||||
*data = NULL;
|
||||
*destroy_notify = NULL;
|
||||
}
|
||||
else if (i != tstack->n_toggle_refs)
|
||||
tstack->toggle_refs[i] = tstack->toggle_refs[tstack->n_toggle_refs];
|
||||
|
Reference in New Issue
Block a user