[glib/g-property: 4/10] gproperty: Updates after review



commit c44f7a209841a0573d61824cc11c4110c26a6b0b
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Wed May 18 08:04:24 2011 +0100

    gproperty: Updates after review
    
    First round of updates past Matthias' review:
    
      - reduce the size of the Property structure by using guint16 for
        the offsets instead of a full gssize;
    
      - upon its first invocation, store the default value set using
        g_property_set_default_value() inside a separate GValue, to
        avoid creating a hash table for the common case of a property
        with no overrides;
    
      - use direct hashing for the overridden defaults hash table, as
        the type names we use as keys are interned;
    
      - compute the lock quark on installation, if the property is
        atomic and it's using the default locking mechanism; the
        default locking uses the quark instead of the string to
        retrieve the bitlock.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=648526

 gobject/gproperty.c |  204 ++++++++++++++++++++++++++++++++-------------------
 1 files changed, 128 insertions(+), 76 deletions(-)
---
diff --git a/gobject/gproperty.c b/gobject/gproperty.c
index a17e0e5..dcc3942 100644
--- a/gobject/gproperty.c
+++ b/gobject/gproperty.c
@@ -441,17 +441,22 @@ struct _GProperty
   GType gtype;
   GType class_gtype;
 
-  gssize type_size;
-  gssize priv_offset;
-  gssize field_offset;
+  guint16 type_size;
+  guint16 priv_offset;
+  guint16 field_offset;
 
-  GHashTable *default_values;
+  GValue *default_value;
+
+  GHashTable *overridden_defaults;
 
   GType prerequisite;
 
   GPropertyLockFunc lock_func;
   GPropertyUnlockFunc unlock_func;
 
+  /* used by the default locking */
+  GQuark lock_quark;
+
   guint is_installed : 1;
 };
 
@@ -735,6 +740,37 @@ g_##g_t##_property_get_value (GProperty *property, \
     } \
 }
 
+static void
+g_property_default_lock (GProperty *property,
+                         gpointer   gobject)
+{
+  gpointer bit_lock_p;
+
+  bit_lock_p = g_object_get_qdata (gobject, property->lock_quark);
+  if (bit_lock_p == NULL)
+    {
+      bit_lock_p = g_new0 (gint, 1);
+      g_object_set_qdata (gobject, property->lock_quark, bit_lock_p);
+    }
+
+  g_bit_lock (bit_lock_p, 0);
+}
+
+static void
+g_property_default_unlock (GProperty *property,
+                           gpointer   gobject)
+{
+  gpointer bit_lock_p;
+
+  bit_lock_p = g_object_get_qdata (gobject, property->lock_quark);
+  if (G_UNLIKELY (bit_lock_p == NULL))
+    return;
+
+  g_object_set_qdata (gobject, property->lock_quark, NULL);
+  g_bit_unlock (bit_lock_p, 0);
+  g_free (bit_lock_p);
+}
+
 static inline void
 property_lock_internal (GProperty *property,
                         gpointer   gobject)
@@ -744,6 +780,8 @@ property_lock_internal (GProperty *property,
 
   if (property->lock_func != NULL)
     property->lock_func (property, gobject);
+  else
+    g_property_default_lock (property, gobject);
 }
 
 static inline void
@@ -755,6 +793,8 @@ property_unlock_internal (GProperty *property,
 
   if (property->unlock_func != NULL)
     property->unlock_func (property, gobject);
+  else
+    g_property_default_unlock (property, gobject);
 }
 
 static inline gpointer
@@ -2831,6 +2871,19 @@ _g_property_set_installed (GProperty *property,
   else
     property->priv_offset = -1;
 
+  /* if the property is using the default locking, pre-compute the
+   * quark for the lock
+   */
+  if ((property->flags & G_PROPERTY_ATOMIC) != 0 &&
+      property->lock_func == NULL)
+    {
+      gchar *lock_n = g_strconcat ("__g_property_lock_",
+                                   G_PARAM_SPEC (property)->name,
+                                   NULL);
+      property->lock_quark = g_quark_from_string (lock_n);
+      g_free (lock_n);
+    }
+
   property->class_gtype = class_gtype;
   property->is_installed = TRUE;
 }
@@ -3448,13 +3501,38 @@ g_property_set_default_value (GProperty    *property,
 
   g_return_if_fail (g_value_type_transformable (G_VALUE_TYPE (default_value), gtype));
 
-  if (property->default_values == NULL)
-    property->default_values = g_hash_table_new_full (g_str_hash, g_str_equal,
-                                                      g_free,
-                                                      g_free);
+  /* if this is the first time g_property_set_default() has been called
+   * on this property, then we special-case it, and we use a single
+   * GValue, to avoid creating an hash table for the common case of a
+   * property with a single default.
+   */
+  if (property->default_value == NULL)
+    {
+      property->default_value = g_new0 (GValue, 1);
+      g_value_init (property->default_value, gtype);
+      if (!g_value_transform (default_value, property->default_value))
+        {
+          g_critical (G_STRLOC ": unable to set the default value for "
+                      "property '%s': the type %s of the value is not "
+                      "compatible with the type of the %s property",
+                      G_PARAM_SPEC (property)->name,
+                      g_type_name (G_VALUE_TYPE (default_value)),
+                      g_type_name (gtype));
+
+          g_value_unset (property->default_value);
+          g_free (property->default_value);
+        }
+
+      return;
+    }
+
+  if (property->overridden_defaults == NULL)
+    property->overridden_defaults = g_hash_table_new_full (NULL, NULL,
+                                                           g_free,
+                                                           g_free);
 
   gtype_name = g_type_name (G_TYPE_FROM_CLASS (gobject_class));
-  if (g_hash_table_lookup (property->default_values, gtype_name) != NULL)
+  if (g_hash_table_lookup (property->overridden_defaults, gtype_name) != NULL)
     {
       g_critical (G_STRLOC ": a default value of property '%s' for "
                   "type '%s' has already been defined.",
@@ -3479,9 +3557,7 @@ g_property_set_default_value (GProperty    *property,
       return;
     }
 
-  g_hash_table_insert (property->default_values,
-                       g_strdup (gtype_name),
-                       value);
+  g_hash_table_insert (property->overridden_defaults, (gpointer) gtype_name, value);
 }
 
 /**
@@ -3507,11 +3583,25 @@ g_property_get_default_value_for_type (GProperty *property,
   g_return_if_fail (property->gtype != G_TYPE_INVALID);
   g_return_if_fail (g_type_name (gtype) != 0);
 
-  if (property->default_values != NULL)
+  if (property->default_value != NULL)
+    {
+      if (!g_value_transform (property->default_value, value))
+        {
+          g_critical (G_STRLOC ": Unable to copy the default value "
+                      "of property '%s' from type '%s' to type '%s'",
+                      G_PARAM_SPEC (property)->name,
+                      g_type_name (property->gtype),
+                      g_type_name (G_VALUE_TYPE (value)));
+        }
+
+      return;
+    }
+
+  if (property->overridden_defaults != NULL)
     {
       GValue *default_value;
 
-      default_value = g_hash_table_lookup (property->default_values,
+      default_value = g_hash_table_lookup (property->overridden_defaults,
                                            g_type_name (gtype));
 
       if (default_value != NULL)
@@ -3619,7 +3709,7 @@ g_property_get_default (GProperty *property,
                         ...)
 {
   GValue value = { 0, };
-  GType p_type;
+  GType gtype, p_type;
   gchar *error;
   va_list var_args;
 
@@ -3627,6 +3717,8 @@ g_property_get_default (GProperty *property,
   g_return_if_fail (G_IS_OBJECT (gobject));
   g_return_if_fail (property->gtype != G_TYPE_INVALID);
 
+  gtype = G_OBJECT_TYPE (gobject);
+
   if (property->prerequisite != G_TYPE_INVALID)
     p_type = property->prerequisite;
   else
@@ -3634,15 +3726,20 @@ g_property_get_default (GProperty *property,
 
   g_value_init (&value, p_type);
 
-  if (property->default_values != NULL)
+  if (property->default_value != NULL)
+    {
+      g_value_copy (property->default_value, &value);
+      goto lcopy;
+    }
+
+  if (property->overridden_defaults != NULL)
     {
-      GType gtype = G_OBJECT_TYPE (gobject);
       GValue *default_value = NULL;
 
       /* we need to recurse through the inheritance chain... */
       while (gtype != G_TYPE_INVALID && default_value == NULL)
         {
-          default_value = g_hash_table_lookup (property->default_values,
+          default_value = g_hash_table_lookup (property->overridden_defaults,
                                                g_type_name (gtype));
 
           gtype = g_type_parent (gtype);
@@ -3659,7 +3756,7 @@ g_property_get_default (GProperty *property,
           ifaces = g_type_interfaces (gtype, &n_ifaces);
           while (n_ifaces-- && default_value == NULL)
             {
-              default_value = g_hash_table_lookup (property->default_values,
+              default_value = g_hash_table_lookup (property->overridden_defaults,
                                                    g_type_name (ifaces[n_ifaces]));
             }
 
@@ -3677,7 +3774,7 @@ g_property_get_default (GProperty *property,
         g_value_copy (default_value, &value);
     }
 
-
+lcopy:
   va_start (var_args, gobject);
 
   G_VALUE_LCOPY (&value, var_args, 0, &error);
@@ -5170,51 +5267,6 @@ g_property_unlock (GProperty *property,
   property_unlock_internal (property, gobject);
 }
 
-static void
-g_property_default_lock (GProperty *property,
-                         gpointer   gobject)
-{
-  gchar *lock_name = g_strconcat ("__g_property_lock_",
-                                  G_PARAM_SPEC (property)->name,
-                                  NULL);
-  gint *bit_lock_p;
-
-  bit_lock_p = g_object_get_data (gobject, lock_name);
-  if (bit_lock_p == NULL)
-    {
-      bit_lock_p = g_new0 (gint, 1);
-
-      g_object_set_data (gobject, lock_name, bit_lock_p);
-    }
-
-  g_free (lock_name);
-
-  g_bit_lock (bit_lock_p, 0);
-}
-
-static void
-g_property_default_unlock (GProperty *property,
-                           gpointer   gobject)
-{
-  gchar *lock_name = g_strconcat ("__g_property_lock_",
-                                  G_PARAM_SPEC (property)->name,
-                                  NULL);
-  gpointer bit_lock_p;
-
-  bit_lock_p = g_object_get_data (gobject, lock_name);
-  if (bit_lock_p == NULL)
-    {
-      g_free (lock_name);
-      return;
-    }
-
-  g_object_set_data (gobject, lock_name, NULL);
-  g_free (lock_name);
-
-  g_bit_unlock (bit_lock_p, 0);
-  g_free (bit_lock_p);
-}
-
 /**
  * g_property_set_lock_functions:
  * @property: a #GProperty
@@ -5237,13 +5289,7 @@ g_property_set_lock_functions (GProperty           *property,
   g_return_if_fail (!property->is_installed);
 
   if (lock_func == NULL)
-    {
-      g_return_if_fail (unlock_func == NULL);
-      lock_func = g_property_default_lock;
-    }
-
-  if (unlock_func == NULL)
-    unlock_func = g_property_default_unlock;
+    g_return_if_fail (unlock_func == NULL);
 
   property->lock_func = lock_func;
   property->unlock_func = unlock_func;
@@ -5255,8 +5301,14 @@ property_finalize (GParamSpec *pspec)
   GProperty *property = G_PROPERTY (pspec);
   GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PROPERTY));
 
-  if (property->default_values != NULL)
-    g_hash_table_destroy (property->default_values);
+  if (property->default_value != NULL)
+    {
+      g_value_unset (property->default_value);
+      g_free (property->default_value);
+    }
+
+  if (property->overridden_defaults != NULL)
+    g_hash_table_destroy (property->overridden_defaults);
 
   parent_class->finalize (pspec);
 }
@@ -5320,8 +5372,8 @@ property_init (GParamSpec *pspec)
   property->field_offset = -1;
   property->priv_offset = -1;
 
-  property->lock_func = g_property_default_lock;
-  property->unlock_func = g_property_default_unlock;
+  property->lock_func = NULL;
+  property->unlock_func = NULL;
 }
 
 GType



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