mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-22 18:22:11 +01:00
Merge branch 'wip/3v1n0/gmain-more-atomic' into 'main'
gmain: Use atomic logic to handle internal GSource flags See merge request GNOME/glib!4488
This commit is contained in:
commit
3a4beabc29
@ -755,8 +755,11 @@ repeatedly_connecting_thread (gpointer data)
|
||||
|
||||
for (guint i = 0; i < iterations; ++i)
|
||||
{
|
||||
gboolean callback_called = FALSE; /* (atomic) */
|
||||
gboolean callback_called; /* (atomic) */
|
||||
gboolean called;
|
||||
|
||||
g_atomic_int_set (&callback_called, FALSE);
|
||||
|
||||
gulong id = g_cancellable_connect (cancellable,
|
||||
G_CALLBACK (on_racy_cancellable_cancelled),
|
||||
&callback_called, NULL);
|
||||
@ -780,13 +783,14 @@ test_cancellable_cancel_reset_connect_races (void)
|
||||
GThread *resetting_thread = NULL;
|
||||
GThread *cancelling_thread = NULL;
|
||||
GThread *connecting_thread = NULL;
|
||||
gboolean callback_called = FALSE; /* (atomic) */
|
||||
gboolean callback_called; /* (atomic) */
|
||||
|
||||
g_test_summary ("Tests threads racing for cancelling, connecting and disconnecting "
|
||||
" and resetting a GCancellable");
|
||||
|
||||
cancellable = g_cancellable_new ();
|
||||
|
||||
g_atomic_int_set (&callback_called, FALSE);
|
||||
g_cancellable_connect (cancellable, G_CALLBACK (on_racy_cancellable_cancelled),
|
||||
&callback_called, NULL);
|
||||
g_assert_false (g_atomic_int_get (&callback_called));
|
||||
|
66
glib/gmain.c
66
glib/gmain.c
@ -32,6 +32,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "glib.h"
|
||||
#include "glibconfig.h"
|
||||
#include "glib_trace.h"
|
||||
|
||||
@ -307,8 +308,10 @@ typedef struct _GSourceIter
|
||||
#define UNLOCK_CONTEXT(context) g_mutex_unlock (&context->mutex)
|
||||
#define G_THREAD_SELF g_thread_self ()
|
||||
|
||||
#define SOURCE_DESTROYED(source) (((source)->flags & G_HOOK_FLAG_ACTIVE) == 0)
|
||||
#define SOURCE_BLOCKED(source) (((source)->flags & G_SOURCE_BLOCKED) != 0)
|
||||
#define SOURCE_DESTROYED(source) \
|
||||
((g_atomic_int_get (&((source)->flags)) & G_HOOK_FLAG_ACTIVE) == 0)
|
||||
#define SOURCE_BLOCKED(source) \
|
||||
((g_atomic_int_get (&((source)->flags)) & G_SOURCE_BLOCKED) != 0)
|
||||
|
||||
/* Forward declarations */
|
||||
|
||||
@ -930,11 +933,11 @@ g_source_new (GSourceFuncs *source_funcs,
|
||||
source = (GSource*) g_malloc0 (struct_size);
|
||||
source->priv = g_slice_new0 (GSourcePrivate);
|
||||
source->source_funcs = source_funcs;
|
||||
source->ref_count = 1;
|
||||
g_atomic_int_set (&source->ref_count, 1);
|
||||
|
||||
source->priority = G_PRIORITY_DEFAULT;
|
||||
|
||||
source->flags = G_HOOK_FLAG_ACTIVE;
|
||||
g_atomic_int_set (&source->flags, G_HOOK_FLAG_ACTIVE);
|
||||
|
||||
source->priv->ready_time = -1;
|
||||
|
||||
@ -976,10 +979,14 @@ void
|
||||
g_source_set_dispose_function (GSource *source,
|
||||
GSourceDisposeFunc dispose)
|
||||
{
|
||||
gboolean was_unset G_GNUC_UNUSED;
|
||||
|
||||
g_return_if_fail (source != NULL);
|
||||
g_return_if_fail (source->priv->dispose == NULL);
|
||||
g_return_if_fail (g_atomic_int_get (&source->ref_count) > 0);
|
||||
source->priv->dispose = dispose;
|
||||
|
||||
was_unset = g_atomic_pointer_compare_and_exchange (&source->priv->dispose,
|
||||
NULL, dispose);
|
||||
g_return_if_fail (was_unset);
|
||||
}
|
||||
|
||||
/* Holds context's lock */
|
||||
@ -1285,7 +1292,7 @@ g_source_destroy_internal (GSource *source,
|
||||
gpointer old_cb_data;
|
||||
GSourceCallbackFuncs *old_cb_funcs;
|
||||
|
||||
source->flags &= ~G_HOOK_FLAG_ACTIVE;
|
||||
g_atomic_int_and (&source->flags, ~G_HOOK_FLAG_ACTIVE);
|
||||
|
||||
old_cb_data = source->callback_data;
|
||||
old_cb_funcs = source->callback_funcs;
|
||||
@ -1359,7 +1366,7 @@ g_source_destroy (GSource *source)
|
||||
if (context)
|
||||
g_source_destroy_internal (source, context, FALSE);
|
||||
else
|
||||
source->flags &= ~G_HOOK_FLAG_ACTIVE;
|
||||
g_atomic_int_and (&source->flags, ~G_HOOK_FLAG_ACTIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2007,9 +2014,9 @@ g_source_set_can_recurse (GSource *source,
|
||||
LOCK_CONTEXT (context);
|
||||
|
||||
if (can_recurse)
|
||||
source->flags |= G_SOURCE_CAN_RECURSE;
|
||||
g_atomic_int_or (&source->flags, G_SOURCE_CAN_RECURSE);
|
||||
else
|
||||
source->flags &= ~G_SOURCE_CAN_RECURSE;
|
||||
g_atomic_int_and (&source->flags, ~G_SOURCE_CAN_RECURSE);
|
||||
|
||||
if (context)
|
||||
UNLOCK_CONTEXT (context);
|
||||
@ -2030,7 +2037,7 @@ g_source_get_can_recurse (GSource *source)
|
||||
g_return_val_if_fail (source != NULL, FALSE);
|
||||
g_return_val_if_fail (g_atomic_int_get (&source->ref_count) > 0, FALSE);
|
||||
|
||||
return (source->flags & G_SOURCE_CAN_RECURSE) != 0;
|
||||
return (g_atomic_int_get (&source->flags) & G_SOURCE_CAN_RECURSE) != 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2246,11 +2253,13 @@ retry_beginning:
|
||||
if (old_ref == 1)
|
||||
{
|
||||
/* If there's a dispose function, call this first */
|
||||
if (source->priv->dispose)
|
||||
GSourceDisposeFunc dispose_func;
|
||||
|
||||
if ((dispose_func = g_atomic_pointer_get (&source->priv->dispose)))
|
||||
{
|
||||
if (context)
|
||||
UNLOCK_CONTEXT (context);
|
||||
source->priv->dispose (source);
|
||||
dispose_func (source);
|
||||
if (context)
|
||||
LOCK_CONTEXT (context);
|
||||
}
|
||||
@ -3267,7 +3276,7 @@ block_source (GSource *source)
|
||||
|
||||
g_return_if_fail (!SOURCE_BLOCKED (source));
|
||||
|
||||
source->flags |= G_SOURCE_BLOCKED;
|
||||
g_atomic_int_or (&source->flags, G_SOURCE_BLOCKED);
|
||||
|
||||
if (source->context)
|
||||
{
|
||||
@ -3302,7 +3311,7 @@ unblock_source (GSource *source)
|
||||
g_return_if_fail (SOURCE_BLOCKED (source)); /* Source already unblocked */
|
||||
g_return_if_fail (!SOURCE_DESTROYED (source));
|
||||
|
||||
source->flags &= ~G_SOURCE_BLOCKED;
|
||||
g_atomic_int_and (&source->flags, ~G_SOURCE_BLOCKED);
|
||||
|
||||
tmp_list = source->poll_fds;
|
||||
while (tmp_list)
|
||||
@ -3339,7 +3348,7 @@ g_main_dispatch (GMainContext *context)
|
||||
context->pending_dispatches->pdata[i] = NULL;
|
||||
g_assert (source);
|
||||
|
||||
source->flags &= ~G_SOURCE_READY;
|
||||
g_atomic_int_and (&source->flags, ~G_SOURCE_READY);
|
||||
|
||||
if (!SOURCE_DESTROYED (source))
|
||||
{
|
||||
@ -3363,11 +3372,12 @@ g_main_dispatch (GMainContext *context)
|
||||
if (cb_funcs)
|
||||
cb_funcs->ref (cb_data);
|
||||
|
||||
if ((source->flags & G_SOURCE_CAN_RECURSE) == 0)
|
||||
if ((g_atomic_int_get (&source->flags) & G_SOURCE_CAN_RECURSE) == 0)
|
||||
block_source (source);
|
||||
|
||||
was_in_call = source->flags & G_HOOK_FLAG_IN_CALL;
|
||||
source->flags |= G_HOOK_FLAG_IN_CALL;
|
||||
was_in_call = g_atomic_int_or (&source->flags,
|
||||
(GSourceFlags) G_HOOK_FLAG_IN_CALL) &
|
||||
G_HOOK_FLAG_IN_CALL;
|
||||
|
||||
if (cb_funcs)
|
||||
cb_funcs->get (cb_data, source, &callback, &user_data);
|
||||
@ -3404,9 +3414,9 @@ g_main_dispatch (GMainContext *context)
|
||||
LOCK_CONTEXT (context);
|
||||
|
||||
if (!was_in_call)
|
||||
source->flags &= ~G_HOOK_FLAG_IN_CALL;
|
||||
g_atomic_int_and (&source->flags, ~G_HOOK_FLAG_IN_CALL);
|
||||
|
||||
if (SOURCE_BLOCKED (source) && !SOURCE_DESTROYED (source))
|
||||
if (SOURCE_BLOCKED (source) && !SOURCE_DESTROYED (source))
|
||||
unblock_source (source);
|
||||
|
||||
/* Note: this depends on the fact that we can't switch
|
||||
@ -3773,7 +3783,7 @@ g_main_context_prepare_unlocked (GMainContext *context,
|
||||
if ((n_ready > 0) && (source->priority > current_priority))
|
||||
break;
|
||||
|
||||
if (!(source->flags & G_SOURCE_READY))
|
||||
if (!(g_atomic_int_get (&source->flags) & G_SOURCE_READY))
|
||||
{
|
||||
gboolean result;
|
||||
gboolean (* prepare) (GSource *source,
|
||||
@ -3834,13 +3844,13 @@ g_main_context_prepare_unlocked (GMainContext *context,
|
||||
|
||||
while (ready_source)
|
||||
{
|
||||
ready_source->flags |= G_SOURCE_READY;
|
||||
g_atomic_int_or (&ready_source->flags, G_SOURCE_READY);
|
||||
ready_source = ready_source->priv->parent_source;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (source->flags & G_SOURCE_READY)
|
||||
if (g_atomic_int_get (&source->flags) & G_SOURCE_READY)
|
||||
{
|
||||
n_ready++;
|
||||
current_priority = source->priority;
|
||||
@ -4106,8 +4116,8 @@ g_main_context_check_unlocked (GMainContext *context,
|
||||
if ((n_ready > 0) && (source->priority > max_priority))
|
||||
break;
|
||||
|
||||
if (!(source->flags & G_SOURCE_READY))
|
||||
{
|
||||
if (!(g_atomic_int_get (&source->flags) & G_SOURCE_READY))
|
||||
{
|
||||
gboolean result;
|
||||
gboolean (* check) (GSource *source);
|
||||
|
||||
@ -4177,13 +4187,13 @@ g_main_context_check_unlocked (GMainContext *context,
|
||||
|
||||
while (ready_source)
|
||||
{
|
||||
ready_source->flags |= G_SOURCE_READY;
|
||||
g_atomic_int_or (&ready_source->flags, G_SOURCE_READY);
|
||||
ready_source = ready_source->priv->parent_source;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (source->flags & G_SOURCE_READY)
|
||||
if (g_atomic_int_get (&source->flags) & G_SOURCE_READY)
|
||||
{
|
||||
g_source_ref (source);
|
||||
g_ptr_array_add (context->pending_dispatches, source);
|
||||
|
@ -275,7 +275,7 @@ struct _GSource
|
||||
GMainContext *context;
|
||||
|
||||
gint priority;
|
||||
guint flags;
|
||||
guint flags; /* (atomic) */
|
||||
guint source_id;
|
||||
|
||||
GSList *poll_fds;
|
||||
|
Loading…
x
Reference in New Issue
Block a user