mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-05-02 03:56:53 +02:00
gobject: add needs_notify flag per object for efficient lookup
The class of a GObject cannot change during its lifetime. And also the the class itself not change (e.g. change the virtual methods). As such, we can cache CLASS_NEEDS_NOTIFY() per object. This way, our _g_object_has_notify_handler() only needs to compare the flags, instead of fetching the class and check the vtable. You might think, CLASS_NEEDS_NOTIFY() is cheaper to check, because it doesn't need an atomic operation to fetch the class and compare the vtable (unlike checking the object's optional-flags). You might also think a constant flag should not be attached to the object's optional-flags (which otherwise change). However, in all cases where we care about CLASS_NEEDS_NOTIFY(), we anyway also check for OPTIONAL_FLAG_HAS_NOTIFY_HANDLER which is right beside in the the optional-flags. So having the OPTIONAL_FLAG_HAS_NEEDS_NOTIFY flag right beside has no downside.
This commit is contained in:
parent
0d596bab12
commit
490604e6d1
@ -109,6 +109,7 @@ enum {
|
|||||||
#define OPTIONAL_FLAG_HAS_NOTIFY_HANDLER (1 << 2) /* Same, specifically for "notify" */
|
#define OPTIONAL_FLAG_HAS_NOTIFY_HANDLER (1 << 2) /* Same, specifically for "notify" */
|
||||||
#define OPTIONAL_FLAG_LOCK (1 << 3) /* _OPTIONAL_BIT_LOCK */
|
#define OPTIONAL_FLAG_LOCK (1 << 3) /* _OPTIONAL_BIT_LOCK */
|
||||||
#define OPTIONAL_FLAG_EVER_HAD_WEAK_REF (1 << 4) /* whether on the object ever g_weak_ref_set() was called. */
|
#define OPTIONAL_FLAG_EVER_HAD_WEAK_REF (1 << 4) /* whether on the object ever g_weak_ref_set() was called. */
|
||||||
|
#define OPTIONAL_FLAG_NEEDS_NOTIFY (1 << 5) /* Corresponds to CLASS_NEEDS_NOTIFY(). */
|
||||||
|
|
||||||
/* We use g_bit_lock(), which only supports one lock per integer.
|
/* We use g_bit_lock(), which only supports one lock per integer.
|
||||||
*
|
*
|
||||||
@ -1770,11 +1771,16 @@ _g_object_has_signal_handler (GObject *object)
|
|||||||
return (object_get_optional_flags (object) & OPTIONAL_FLAG_HAS_SIGNAL_HANDLER) != 0;
|
return (object_get_optional_flags (object) & OPTIONAL_FLAG_HAS_SIGNAL_HANDLER) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline gboolean
|
||||||
|
_g_object_has_notify_handler_for_flags (guint flags)
|
||||||
|
{
|
||||||
|
return (flags & (OPTIONAL_FLAG_HAS_NOTIFY_HANDLER | OPTIONAL_FLAG_NEEDS_NOTIFY)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline gboolean
|
static inline gboolean
|
||||||
_g_object_has_notify_handler (GObject *object)
|
_g_object_has_notify_handler (GObject *object)
|
||||||
{
|
{
|
||||||
return CLASS_NEEDS_NOTIFY (G_OBJECT_GET_CLASS (object)) ||
|
return _g_object_has_notify_handler_for_flags (object_get_optional_flags (object));
|
||||||
(object_get_optional_flags (object) & OPTIONAL_FLAG_HAS_NOTIFY_HANDLER) != 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1782,8 +1788,10 @@ _g_object_set_has_signal_handler (GObject *object,
|
|||||||
guint signal_id)
|
guint signal_id)
|
||||||
{
|
{
|
||||||
guint flags = OPTIONAL_FLAG_HAS_SIGNAL_HANDLER;
|
guint flags = OPTIONAL_FLAG_HAS_SIGNAL_HANDLER;
|
||||||
|
|
||||||
if (signal_id == gobject_signals[NOTIFY])
|
if (signal_id == gobject_signals[NOTIFY])
|
||||||
flags |= OPTIONAL_FLAG_HAS_NOTIFY_HANDLER;
|
flags |= OPTIONAL_FLAG_HAS_NOTIFY_HANDLER;
|
||||||
|
|
||||||
object_set_optional_flags (object, flags);
|
object_set_optional_flags (object, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1804,6 +1812,7 @@ g_object_init (GObject *object,
|
|||||||
GObjectClass *class)
|
GObjectClass *class)
|
||||||
{
|
{
|
||||||
guint *p_flags;
|
guint *p_flags;
|
||||||
|
gboolean needs_notify = CLASS_NEEDS_NOTIFY (class);
|
||||||
|
|
||||||
object->ref_count = 1;
|
object->ref_count = 1;
|
||||||
object->qdata = NULL;
|
object->qdata = NULL;
|
||||||
@ -1812,8 +1821,10 @@ g_object_init (GObject *object,
|
|||||||
* without atomic. */
|
* without atomic. */
|
||||||
p_flags = object_get_optional_flags_p (object);
|
p_flags = object_get_optional_flags_p (object);
|
||||||
*p_flags = OPTIONAL_FLAG_IN_CONSTRUCTION;
|
*p_flags = OPTIONAL_FLAG_IN_CONSTRUCTION;
|
||||||
|
if (needs_notify)
|
||||||
|
*p_flags |= OPTIONAL_FLAG_NEEDS_NOTIFY;
|
||||||
|
|
||||||
if (CLASS_HAS_PROPS (class) && CLASS_NEEDS_NOTIFY (class))
|
if (CLASS_HAS_PROPS (class) && needs_notify)
|
||||||
{
|
{
|
||||||
/* freeze object's notification queue, g_object_new_internal() preserves pairedness */
|
/* freeze object's notification queue, g_object_new_internal() preserves pairedness */
|
||||||
g_object_notify_queue_freeze (object, TRUE);
|
g_object_notify_queue_freeze (object, TRUE);
|
||||||
@ -2021,8 +2032,7 @@ g_object_notify_by_spec_internal (GObject *object,
|
|||||||
/* get all flags we need with a single atomic read */
|
/* get all flags we need with a single atomic read */
|
||||||
object_flags = object_get_optional_flags (object);
|
object_flags = object_get_optional_flags (object);
|
||||||
|
|
||||||
needs_notify = ((object_flags & OPTIONAL_FLAG_HAS_NOTIFY_HANDLER) != 0) ||
|
needs_notify = _g_object_has_notify_handler_for_flags (object_flags);
|
||||||
CLASS_NEEDS_NOTIFY (G_OBJECT_GET_CLASS (object));
|
|
||||||
|
|
||||||
if (!needs_notify)
|
if (!needs_notify)
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user