[glib/resources-extraneous-symbol: 1/2] Add g_object_notify_by_pspecs




commit 020597920458d0b23066b6477e90051e06f1f266
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri May 6 16:17:45 2022 -0400

    Add g_object_notify_by_pspecs
    
    This is an attempt to reduce the overhead of looking
    up the notify queue for each property.

 gobject/gobject.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++--------
 gobject/gobject.h |  4 +++
 2 files changed, 73 insertions(+), 11 deletions(-)
---
diff --git a/gobject/gobject.c b/gobject/gobject.c
index d33d8e5b04..81911f9142 100644
--- a/gobject/gobject.c
+++ b/gobject/gobject.c
@@ -368,6 +368,28 @@ g_object_notify_queue_add (GObject            *object,
   G_UNLOCK(notify_lock);
 }
 
+static inline void
+g_object_notify_queue_add_many (GObject             *object,
+                                GObjectNotifyQueue  *nqueue,
+                                GParamSpec         **pspec,
+                                guint                n)
+{
+  G_LOCK(notify_lock);
+
+  g_assert (nqueue->n_pspecs + n < 65535);
+
+  for (int i = 0; i < n; i++)
+    {
+      if (g_slist_find (nqueue->pspecs, pspec[i]) == NULL)
+        {
+          nqueue->pspecs = g_slist_prepend (nqueue->pspecs, pspec[i]);
+          nqueue->n_pspecs++;
+        }
+    }
+
+  G_UNLOCK(notify_lock);
+}
+
 #ifdef G_ENABLE_DEBUG
 G_LOCK_DEFINE_STATIC     (debug_objects);
 static guint            debug_objects_count = 0;
@@ -1297,7 +1319,7 @@ g_object_freeze_notify (GObject *object)
   g_object_unref (object);
 }
 
-static GParamSpec *
+static inline GParamSpec *
 get_notify_pspec (GParamSpec *pspec)
 {
   GParamSpec *redirected;
@@ -1316,14 +1338,23 @@ get_notify_pspec (GParamSpec *pspec)
 }
 
 static inline void
-g_object_notify_by_spec_internal (GObject    *object,
-                                 GParamSpec *pspec)
+g_object_notify_by_spec_internal (GObject     *object,
+                                 GParamSpec **pspecs,
+                                  guint        n_pspec)
 {
-  GParamSpec *notify_pspec;
+  GParamSpec **notify_pspecs;
+  guint n = 0;
 
-  notify_pspec = get_notify_pspec (pspec);
+  notify_pspecs = g_alloca (sizeof (GParamSpec *) * n_pspec);
 
-  if (notify_pspec != NULL)
+  for (int i = 0; i < n_pspec; i++)
+    {
+      notify_pspecs[n] = get_notify_pspec (pspecs[i]);
+      if (notify_pspecs[n])
+        n++;
+    }
+
+  if (n > 0)
     {
       GObjectNotifyQueue *nqueue;
 
@@ -1333,13 +1364,13 @@ g_object_notify_by_spec_internal (GObject    *object,
       if (nqueue != NULL)
         {
           /* we're frozen, so add to the queue and release our freeze */
-          g_object_notify_queue_add (object, nqueue, notify_pspec);
+          g_object_notify_queue_add_many (object, nqueue, notify_pspecs, n);
           g_object_notify_queue_thaw (object, nqueue);
         }
       else
         /* not frozen, so just dispatch the notification directly */
         G_OBJECT_GET_CLASS (object)
-          ->dispatch_properties_changed (object, 1, &notify_pspec);
+          ->dispatch_properties_changed (object, n, notify_pspecs);
     }
 }
 
@@ -1386,7 +1417,7 @@ g_object_notify (GObject     *object,
               G_OBJECT_TYPE_NAME (object),
               property_name);
   else
-    g_object_notify_by_spec_internal (object, pspec);
+    g_object_notify_by_spec_internal (object, &pspec, 1);
   g_object_unref (object);
 }
 
@@ -1440,7 +1471,6 @@ void
 g_object_notify_by_pspec (GObject    *object,
                          GParamSpec *pspec)
 {
-
   g_return_if_fail (G_IS_OBJECT (object));
   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
 
@@ -1448,7 +1478,35 @@ g_object_notify_by_pspec (GObject    *object,
     return;
 
   g_object_ref (object);
-  g_object_notify_by_spec_internal (object, pspec);
+  g_object_notify_by_spec_internal (object, &pspec, 1);
+  g_object_unref (object);
+}
+
+/**
+ * g_object_notify_by_pspecs:
+ * @object: a #GObject
+ * @pspecs: (array, length=n_pspecs): array of #GParamSpecs of properties installed on the class of @object
+ * @n_pspecs: length of @pspecs
+ *
+ * Emits a "notify" signal for the properties specified by @pspecs on @object.
+ *
+ * This function omits the property name lookup, hence it is faster than
+ * g_object_notify().
+ *
+ * Since: REPLACEME
+ */
+void
+g_object_notify_by_pspecs (GObject     *object,
+                           GParamSpec **pspecs,
+                           guint        n_pspecs)
+{
+  g_return_if_fail (G_IS_OBJECT (object));
+
+  if (g_atomic_int_get (&object->ref_count) == 0)
+    return;
+
+  g_object_ref (object);
+  g_object_notify_by_spec_internal (object, pspecs, n_pspecs);
   g_object_unref (object);
 }
 
diff --git a/gobject/gobject.h b/gobject/gobject.h
index 3dc4f7f480..be3884444b 100644
--- a/gobject/gobject.h
+++ b/gobject/gobject.h
@@ -510,6 +510,10 @@ GLIB_AVAILABLE_IN_ALL
 void        g_object_notify_by_pspec          (GObject        *object,
                                               GParamSpec     *pspec);
 GLIB_AVAILABLE_IN_ALL
+void        g_object_notify_by_pspecs         (GObject        *object,
+                                               GParamSpec    **pspecs,
+                                               guint           n_pspecs);
+GLIB_AVAILABLE_IN_ALL
 void        g_object_thaw_notify              (GObject        *object);
 GLIB_AVAILABLE_IN_ALL
 gboolean    g_object_is_floating             (gpointer        object);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]