mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-09 12:25:48 +01:00
gobject: don't freeze to queue notify event in g_object_notify_by_spec_internal()
Previously: - if the object is currently not frozen, we called g_object_notify_queue_freeze() once. Afterwards dispatch the event directly. This is probably the common case, and requires one notify_lock lock. - if the object is currently frozen, we call g_object_notify_queue_freeze(), g_object_notify_queue_add(). g_object_notify_queue_thaw(). This required taking the notify_lock three times. - if the object is currently not frozen and in_init, then we called g_object_notify_queue_freeze(), g_object_notify_queue_freeze(), g_object_notify_queue_add(). This also required to take the lock three times. There is another thaw at the end of object initialization. That was because we first call g_object_notify_queue_freeze() to see whether we are frozen. And depending on that, queue the event (and thaw again). Instead, g_object_notify_queue_add() can do the check and queueing in one step. There is no need to call a freeze() to (conditionally) enqueue a notification. Now only one lock is taken in all cases. Also, g_object_notify_queue_freeze() and g_object_notify_queue_thaw() both call g_datalist_id_get_data() (which also take a bit lock). As the thaw is no longer necessary, the second lock is also saved.
This commit is contained in:
parent
a2b467624b
commit
94c735a2aa
@ -320,13 +320,41 @@ g_object_notify_queue_thaw (GObject *object,
|
|||||||
g_free (free_me);
|
g_free (free_me);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
g_object_notify_queue_add (GObject *object,
|
g_object_notify_queue_add (GObject *object,
|
||||||
GObjectNotifyQueue *nqueue,
|
GObjectNotifyQueue *nqueue,
|
||||||
GParamSpec *pspec)
|
GParamSpec *pspec,
|
||||||
|
gboolean in_init)
|
||||||
{
|
{
|
||||||
G_LOCK(notify_lock);
|
G_LOCK(notify_lock);
|
||||||
|
|
||||||
|
if (!nqueue)
|
||||||
|
{
|
||||||
|
/* We are called without an nqueue. Figure out whether a notification
|
||||||
|
* should be queued. */
|
||||||
|
nqueue = g_datalist_id_get_data (&object->qdata, quark_notify_queue);
|
||||||
|
|
||||||
|
if (!nqueue)
|
||||||
|
{
|
||||||
|
if (!in_init)
|
||||||
|
{
|
||||||
|
/* We don't have a notify queue and are not in_init. The event
|
||||||
|
* is not to be queued. The caller will dispatch directly. */
|
||||||
|
G_UNLOCK (notify_lock);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We are "in_init", but did not freeze the queue in g_object_init
|
||||||
|
* yet. Instead, we gained a notify handler in instance init, so now
|
||||||
|
* we need to freeze just-in-time.
|
||||||
|
*
|
||||||
|
* Note that this freeze will be balanced at the end of object
|
||||||
|
* initialization.
|
||||||
|
*/
|
||||||
|
nqueue = g_object_notify_queue_create_queue_frozen (object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
g_assert (nqueue->n_pspecs < 65535);
|
g_assert (nqueue->n_pspecs < 65535);
|
||||||
|
|
||||||
if (g_slist_find (nqueue->pspecs, pspec) == NULL)
|
if (g_slist_find (nqueue->pspecs, pspec) == NULL)
|
||||||
@ -336,6 +364,8 @@ g_object_notify_queue_add (GObject *object,
|
|||||||
}
|
}
|
||||||
|
|
||||||
G_UNLOCK(notify_lock);
|
G_UNLOCK(notify_lock);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef G_ENABLE_DEBUG
|
#ifdef G_ENABLE_DEBUG
|
||||||
@ -1506,29 +1536,7 @@ g_object_notify_by_spec_internal (GObject *object,
|
|||||||
|
|
||||||
if (pspec != NULL && needs_notify)
|
if (pspec != NULL && needs_notify)
|
||||||
{
|
{
|
||||||
GObjectNotifyQueue *nqueue;
|
if (!g_object_notify_queue_add (object, NULL, pspec, in_init))
|
||||||
gboolean need_thaw = TRUE;
|
|
||||||
|
|
||||||
/* conditional freeze: only increase freeze count if already frozen */
|
|
||||||
nqueue = g_object_notify_queue_freeze (object, TRUE);
|
|
||||||
if (in_init && !nqueue)
|
|
||||||
{
|
|
||||||
/* We did not freeze the queue in g_object_init, but
|
|
||||||
* we gained a notify handler in instance init, so
|
|
||||||
* now we need to freeze just-in-time
|
|
||||||
*/
|
|
||||||
nqueue = g_object_notify_queue_freeze (object, FALSE);
|
|
||||||
need_thaw = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nqueue != NULL)
|
|
||||||
{
|
|
||||||
/* we're frozen, so add to the queue and release our freeze */
|
|
||||||
g_object_notify_queue_add (object, nqueue, pspec);
|
|
||||||
if (need_thaw)
|
|
||||||
g_object_notify_queue_thaw (object, nqueue, FALSE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Coverity doesn’t understand the paired ref/unref here and seems to
|
* Coverity doesn’t understand the paired ref/unref here and seems to
|
||||||
@ -1825,7 +1833,7 @@ object_set_property (GObject *object,
|
|||||||
|
|
||||||
if ((pspec->flags & (G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READABLE)) == G_PARAM_READABLE &&
|
if ((pspec->flags & (G_PARAM_EXPLICIT_NOTIFY | G_PARAM_READABLE)) == G_PARAM_READABLE &&
|
||||||
nqueue != NULL)
|
nqueue != NULL)
|
||||||
g_object_notify_queue_add (object, nqueue, pspec);
|
g_object_notify_queue_add (object, nqueue, pspec, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
x
Reference in New Issue
Block a user