[glib/gobject-speedups: 23/23] Reduce locking overhead for param specs




commit e4719cc0f1cc36084c7af44037bff1ff060080d5
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu May 19 20:59:37 2022 -0400

    Reduce locking overhead for param specs
    
    Only look the pool once per object construction.

 gobject/gobject.c | 24 ++++++++++++++++++------
 gobject/gparam.c  | 48 +++++++++++++++++++++++++++++-------------------
 gobject/gparam.h  |  6 ++++++
 3 files changed, 53 insertions(+), 25 deletions(-)
---
diff --git a/gobject/gobject.c b/gobject/gobject.c
index 16f7dfe031..85bc57474c 100644
--- a/gobject/gobject.c
+++ b/gobject/gobject.c
@@ -2350,12 +2350,14 @@ g_object_new_valist (GType        object_type,
 
       name = first_property_name;
 
+      g_param_spec_pool_acquire (pspec_pool);
+
       do
         {
           gchar *error = NULL;
           GParamSpec *pspec;
 
-          pspec = g_param_spec_pool_lookup (pspec_pool, name, object_type, TRUE);
+          pspec = g_param_spec_pool_find (pspec_pool, name, object_type, TRUE);
 
           if (!g_object_new_is_valid_property (object_type, pspec, name, params, n_params))
             break;
@@ -2404,6 +2406,8 @@ g_object_new_valist (GType        object_type,
         }
       while ((name = va_arg (var_args, const gchar *)));
 
+      g_param_spec_pool_release (pspec_pool);
+
       object = g_object_new_internal (class, params, n_params);
 
       while (n_params--)
@@ -2531,9 +2535,11 @@ g_object_setv (GObject       *object,
   if (_g_object_has_notify_handler (object))
     nqueue = g_object_notify_queue_freeze (object, FALSE);
 
+  g_param_spec_pool_acquire (pspec_pool);
+
   for (i = 0; i < n_properties; i++)
     {
-      pspec = g_param_spec_pool_lookup (pspec_pool, names[i], obj_type, TRUE);
+      pspec = g_param_spec_pool_find (pspec_pool, names[i], obj_type, TRUE);
 
       if (!g_object_set_is_valid_property (object, pspec, names[i]))
         break;
@@ -2541,6 +2547,8 @@ g_object_setv (GObject       *object,
       object_set_property (object, pspec, &values[i], nqueue);
     }
 
+  g_param_spec_pool_release (pspec_pool);
+
   if (nqueue)
     g_object_notify_queue_thaw (object, nqueue);
 
@@ -2571,6 +2579,8 @@ g_object_set_valist (GObject       *object,
   if (_g_object_has_notify_handler (object))
     nqueue = g_object_notify_queue_freeze (object, FALSE);
   
+  g_param_spec_pool_acquire (pspec_pool);
+
   name = first_property_name;
   while (name)
     {
@@ -2579,10 +2589,10 @@ g_object_set_valist (GObject     *object,
       gchar *error = NULL;
       GTypeValueTable *vtab;
       
-      pspec = g_param_spec_pool_lookup (pspec_pool,
-                                       name,
-                                       G_OBJECT_TYPE (object),
-                                       TRUE);
+      pspec = g_param_spec_pool_find (pspec_pool,
+                                     name,
+                                     G_OBJECT_TYPE (object),
+                                     TRUE);
 
       if (!g_object_set_is_valid_property (object, pspec, name))
         break;
@@ -2604,6 +2614,8 @@ g_object_set_valist (GObject       *object,
       name = va_arg (var_args, gchar*);
     }
 
+  g_param_spec_pool_release (pspec_pool);
+
   if (nqueue)
     g_object_notify_queue_thaw (object, nqueue);
 
diff --git a/gobject/gparam.c b/gobject/gparam.c
index 4311dbbc68..cee48ab65d 100644
--- a/gobject/gparam.c
+++ b/gobject/gparam.c
@@ -1098,21 +1098,41 @@ g_param_spec_pool_lookup (GParamSpecPool *pool,
   g_return_val_if_fail (pool != NULL, NULL);
   g_return_val_if_fail (param_name != NULL, NULL);
 
+  g_param_spec_pool_acquire (pool);
+  pspec = g_param_spec_pool_find (pool, param_name, owner_type, walk_ancestors);
+  g_param_spec_pool_release (pool);
+
+  return pspec;
+}
+
+void
+g_param_spec_pool_acquire (GParamSpecPool *pool)
+{
   g_mutex_lock (&pool->mutex);
+}
+
+void
+g_param_spec_pool_release (GParamSpecPool *pool)
+{
+  g_mutex_unlock (&pool->mutex);
+}
+
+GParamSpec *
+g_param_spec_pool_find (GParamSpecPool *pool,
+                        const char     *param_name,
+                        GType           owner_type,
+                        gboolean        walk_ancestors)
+{
+  GParamSpec *pspec;
 
   /* try quick and away, i.e. without prefix */
   pspec = param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
   if (pspec)
-    {
-      g_mutex_unlock (&pool->mutex);
-      return pspec;
-    }
+    return pspec;
 
   if (pool->type_prefixing)
     {
-      char *delim;
-
-      delim = strchr (param_name, ':');
+      char *delim = strchr (param_name, ':');
 
       /* strip type prefix */
       if (delim && delim[1] == ':')
@@ -1130,25 +1150,15 @@ g_param_spec_pool_lookup (GParamSpecPool *pool,
             {
               /* sanity check, these cases don't make a whole lot of sense */
               if ((!walk_ancestors && type != owner_type) || !g_type_is_a (owner_type, type))
-                {
-                  g_mutex_unlock (&pool->mutex);
+                return NULL;
 
-                  return NULL;
-                }
               owner_type = type;
               param_name += l + 2;
-              pspec = param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
-              g_mutex_unlock (&pool->mutex);
-
-              return pspec;
+              return param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
             }
         }
     }
 
-  /* malformed param_name */
-
-  g_mutex_unlock (&pool->mutex);
-
   return NULL;
 }
 
diff --git a/gobject/gparam.h b/gobject/gparam.h
index fea6e502c8..e562594957 100644
--- a/gobject/gparam.h
+++ b/gobject/gparam.h
@@ -443,6 +443,12 @@ GParamSpec**       g_param_spec_pool_list          (GParamSpecPool *pool,
                                                 GType           owner_type,
                                                 guint          *n_pspecs_p);
 
+void g_param_spec_pool_acquire (GParamSpecPool *pool);
+void g_param_spec_pool_release (GParamSpecPool *pool);
+GParamSpec *g_param_spec_pool_find (GParamSpecPool *pool,
+                                    const char     *param_name,
+                                    GType           owner_type,
+                                    gboolean        walk_ancestors);
 
 /* contracts:
  *


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