From 2bad3cb3bf8f0cc3f45057061f9a538ecf7742b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 14 Feb 2019 17:46:33 +0200 Subject: [PATCH 1/5] Use atomic reference counting for GSource If attached to a context already it would use a mutex instead but at least before that the reference counting is not thread-safe currently. --- glib/gmain.c | 50 +++++++++++++++----------------------------------- 1 file changed, 15 insertions(+), 35 deletions(-) diff --git a/glib/gmain.c b/glib/gmain.c index 26e68823d..5b91c3117 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -374,15 +374,6 @@ typedef struct _GSourceIter #define SOURCE_DESTROYED(source) (((source)->flags & G_HOOK_FLAG_ACTIVE) == 0) #define SOURCE_BLOCKED(source) (((source)->flags & G_SOURCE_BLOCKED) != 0) -#define SOURCE_UNREF(source, context) \ - G_STMT_START { \ - if ((source)->ref_count > 1) \ - (source)->ref_count--; \ - else \ - g_source_unref_internal ((source), (context), TRUE); \ - } G_STMT_END - - /* Forward declarations */ static void g_source_unref_internal (GSource *source, @@ -977,10 +968,10 @@ g_source_iter_next (GSourceIter *iter, GSource **source) */ if (iter->source && iter->may_modify) - SOURCE_UNREF (iter->source, iter->context); + g_source_unref_internal (iter->source, iter->context, TRUE); iter->source = next_source; if (iter->source && iter->may_modify) - iter->source->ref_count++; + g_source_ref (iter->source); *source = iter->source; return *source != NULL; @@ -994,7 +985,7 @@ g_source_iter_clear (GSourceIter *iter) { if (iter->source && iter->may_modify) { - SOURCE_UNREF (iter->source, iter->context); + g_source_unref_internal (iter->source, iter->context, TRUE); iter->source = NULL; } } @@ -1135,7 +1126,7 @@ g_source_attach_unlocked (GSource *source, source->context = context; source->source_id = id; - source->ref_count++; + g_source_ref (source); g_hash_table_insert (context->sources, GUINT_TO_POINTER (id), source); @@ -1675,7 +1666,7 @@ g_source_set_funcs (GSource *source, { g_return_if_fail (source != NULL); g_return_if_fail (source->context == NULL); - g_return_if_fail (source->ref_count > 0); + g_return_if_fail (g_atomic_int_get (&source->ref_count) > 0); g_return_if_fail (funcs != NULL); source->source_funcs = funcs; @@ -2050,19 +2041,9 @@ g_source_set_name_by_id (guint tag, GSource * g_source_ref (GSource *source) { - GMainContext *context; - g_return_val_if_fail (source != NULL, NULL); - context = source->context; - - if (context) - LOCK_CONTEXT (context); - - source->ref_count++; - - if (context) - UNLOCK_CONTEXT (context); + g_atomic_int_inc (&source->ref_count); return source; } @@ -2078,12 +2059,11 @@ g_source_unref_internal (GSource *source, GSourceCallbackFuncs *old_cb_funcs = NULL; g_return_if_fail (source != NULL); - + if (!have_lock && context) LOCK_CONTEXT (context); - source->ref_count--; - if (source->ref_count == 0) + if (g_atomic_int_dec_and_test (&source->ref_count)) { TRACE (GLIB_SOURCE_BEFORE_FREE (source, context, source->source_funcs->finalize)); @@ -2107,20 +2087,20 @@ g_source_unref_internal (GSource *source, { /* Temporarily increase the ref count again so that GSource methods * can be called from finalize(). */ - source->ref_count++; + g_atomic_int_inc (&source->ref_count); if (context) UNLOCK_CONTEXT (context); source->source_funcs->finalize (source); if (context) LOCK_CONTEXT (context); - source->ref_count--; + g_atomic_int_add (&source->ref_count, -1); } if (old_cb_funcs) { /* Temporarily increase the ref count again so that GSource methods * can be called from callback_funcs.unref(). */ - source->ref_count++; + g_atomic_int_inc (&source->ref_count); if (context) UNLOCK_CONTEXT (context); @@ -2128,7 +2108,7 @@ g_source_unref_internal (GSource *source, if (context) LOCK_CONTEXT (context); - source->ref_count--; + g_atomic_int_add (&source->ref_count, -1); } g_free (source->name); @@ -3201,7 +3181,7 @@ g_main_dispatch (GMainContext *context) } } - SOURCE_UNREF (source, context); + g_source_unref_internal (source, context, TRUE); } g_ptr_array_set_size (context->pending_dispatches, 0); @@ -3440,7 +3420,7 @@ g_main_context_prepare (GMainContext *context, for (i = 0; i < context->pending_dispatches->len; i++) { if (context->pending_dispatches->pdata[i]) - SOURCE_UNREF ((GSource *)context->pending_dispatches->pdata[i], context); + g_source_unref_internal ((GSource *)context->pending_dispatches->pdata[i], context, TRUE); } g_ptr_array_set_size (context->pending_dispatches, 0); @@ -3788,7 +3768,7 @@ g_main_context_check (GMainContext *context, if (source->flags & G_SOURCE_READY) { - source->ref_count++; + g_source_ref (source); g_ptr_array_add (context->pending_dispatches, source); n_ready++; -- 2.31.1