[glib] GVariant: avoid locking in a common case



commit 181982c47cde49b3aff2293729f5aee5987db8af
Author: Ryan Lortie <desrt desrt ca>
Date:   Tue Oct 26 11:49:32 2010 -0400

    GVariant: avoid locking in a common case
    
    Avoid acquiring the lock on the instance on the case of deserialising a
    child.  We know that it is safe to do this unlocked because a serialised
    child will never become unserialised.
    
    Closes #626320

 glib/gvariant-core.c |   69 ++++++++++++++++++++++++++++---------------------
 1 files changed, 39 insertions(+), 30 deletions(-)
---
diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
index 6f01930..d783053 100644
--- a/glib/gvariant-core.c
+++ b/glib/gvariant-core.c
@@ -847,41 +847,50 @@ GVariant *
 g_variant_get_child_value (GVariant *value,
                            gsize     index_)
 {
-  GVariant *child = NULL;
+  if (~g_atomic_int_get (&value->state) & STATE_SERIALISED)
+    {
+      g_variant_lock (value);
 
-  g_variant_lock (value);
+      if (~value->state & STATE_SERIALISED)
+        {
+          GVariant *child;
 
-  if (value->state & STATE_SERIALISED)
-    {
-      GVariantSerialised serialised = {
-        value->type_info,
-        (gpointer) value->contents.serialised.data,
-        value->size
-      };
-      GVariantSerialised s_child;
+          child = g_variant_ref (value->contents.tree.children[index_]);
+          g_variant_unlock (value);
 
-      /* get the serialiser to extract the serialised data for the child
-       * from the serialised data for the container
-       */
-      s_child = g_variant_serialised_get_child (serialised, index_);
-
-      /* create a new serialised instance out of it */
-      child = g_slice_new (GVariant);
-      child->type_info = s_child.type_info;
-      child->state = (value->state & STATE_TRUSTED) |
-                     STATE_SERIALISED;
-      child->size = s_child.size;
-      child->ref_count = 1;
-      child->contents.serialised.buffer =
-        g_buffer_ref (value->contents.serialised.buffer);
-      child->contents.serialised.data = s_child.data;
-     }
-  else
-    child = g_variant_ref (value->contents.tree.children[index_]);
+          return child;
+        }
 
-  g_variant_unlock (value);
+      g_variant_unlock (value);
+    }
 
-  return child;
+  {
+    GVariantSerialised serialised = {
+      value->type_info,
+      (gpointer) value->contents.serialised.data,
+      value->size
+    };
+    GVariantSerialised s_child;
+    GVariant *child;
+
+    /* get the serialiser to extract the serialised data for the child
+     * from the serialised data for the container
+     */
+    s_child = g_variant_serialised_get_child (serialised, index_);
+
+    /* create a new serialised instance out of it */
+    child = g_slice_new (GVariant);
+    child->type_info = s_child.type_info;
+    child->state = (value->state & STATE_TRUSTED) |
+                   STATE_SERIALISED;
+    child->size = s_child.size;
+    child->ref_count = 1;
+    child->contents.serialised.buffer =
+      g_buffer_ref (value->contents.serialised.buffer);
+    child->contents.serialised.data = s_child.data;
+
+    return child;
+  }
 }
 
 /**



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