From 181982c47cde49b3aff2293729f5aee5987db8af Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Tue, 26 Oct 2010 11:49:32 -0400 Subject: [PATCH] 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 file changed, 39 insertions(+), 30 deletions(-) diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c index 6f019307a..d78305307 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; - - g_variant_lock (value); - - if (value->state & STATE_SERIALISED) + if (~g_atomic_int_get (&value->state) & STATE_SERIALISED) { - GVariantSerialised serialised = { - value->type_info, - (gpointer) value->contents.serialised.data, - value->size - }; - GVariantSerialised s_child; + g_variant_lock (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_); + if (~value->state & STATE_SERIALISED) + { + GVariant *child; - /* 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_]); + child = g_variant_ref (value->contents.tree.children[index_]); + g_variant_unlock (value); - g_variant_unlock (value); + return child; + } - return child; + g_variant_unlock (value); + } + + { + 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; + } } /**