From 4c243b1cba6e94658e68c3e4b188d0d784ed7463 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Thu, 24 Sep 2009 11:45:13 +0200 Subject: [PATCH] Make type_data_unref_U not take locks in the common case https://bugzilla.gnome.org/show_bug.cgi?id=585375 --- gobject/gtype.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/gobject/gtype.c b/gobject/gtype.c index 2a4925c..af36382 100644 --- a/gobject/gtype.c +++ b/gobject/gtype.c @@ -2346,11 +2346,12 @@ static inline void type_data_unref_U (TypeNode *node, gboolean uncached) { - G_WRITE_LOCK (&type_rw_lock); - g_assert (node->data && NODE_REFCOUNT (node) > 0); - if (NODE_REFCOUNT (node) > 1) - g_atomic_int_add ((int *) &node->ref_count, -1); - else + guint current; + + do { + current = NODE_REFCOUNT (node); + + if (current <= 1) { if (!node->plugin) { @@ -2358,13 +2359,17 @@ type_data_unref_U (TypeNode *node, NODE_NAME (node)); return; } - G_WRITE_UNLOCK (&type_rw_lock); + + g_assert (current > 0); + g_static_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */ G_WRITE_LOCK (&type_rw_lock); type_data_last_unref_Wm (node, uncached); + G_WRITE_UNLOCK (&type_rw_lock); g_static_rec_mutex_unlock (&class_init_rec_mutex); + return; } - G_WRITE_UNLOCK (&type_rw_lock); + } while (!g_atomic_int_compare_and_exchange ((int *) &node->ref_count, current, current - 1)); } /** -- 2.7.4