mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 02:32: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)
|
for (guint i = 0; i < iterations; ++i)
|
||||||
{
|
{
|
||||||
gboolean callback_called = FALSE; /* (atomic) */
|
gboolean callback_called; /* (atomic) */
|
||||||
gboolean called;
|
gboolean called;
|
||||||
|
|
||||||
|
g_atomic_int_set (&callback_called, FALSE);
|
||||||
|
|
||||||
gulong id = g_cancellable_connect (cancellable,
|
gulong id = g_cancellable_connect (cancellable,
|
||||||
G_CALLBACK (on_racy_cancellable_cancelled),
|
G_CALLBACK (on_racy_cancellable_cancelled),
|
||||||
&callback_called, NULL);
|
&callback_called, NULL);
|
||||||
@ -780,13 +783,14 @@ test_cancellable_cancel_reset_connect_races (void)
|
|||||||
GThread *resetting_thread = NULL;
|
GThread *resetting_thread = NULL;
|
||||||
GThread *cancelling_thread = NULL;
|
GThread *cancelling_thread = NULL;
|
||||||
GThread *connecting_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 "
|
g_test_summary ("Tests threads racing for cancelling, connecting and disconnecting "
|
||||||
" and resetting a GCancellable");
|
" and resetting a GCancellable");
|
||||||
|
|
||||||
cancellable = g_cancellable_new ();
|
cancellable = g_cancellable_new ();
|
||||||
|
|
||||||
|
g_atomic_int_set (&callback_called, FALSE);
|
||||||
g_cancellable_connect (cancellable, G_CALLBACK (on_racy_cancellable_cancelled),
|
g_cancellable_connect (cancellable, G_CALLBACK (on_racy_cancellable_cancelled),
|
||||||
&callback_called, NULL);
|
&callback_called, NULL);
|
||||||
g_assert_false (g_atomic_int_get (&callback_called));
|
g_assert_false (g_atomic_int_get (&callback_called));
|
||||||
|
62
glib/gmain.c
62
glib/gmain.c
@ -32,6 +32,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "glib.h"
|
||||||
#include "glibconfig.h"
|
#include "glibconfig.h"
|
||||||
#include "glib_trace.h"
|
#include "glib_trace.h"
|
||||||
|
|
||||||
@ -307,8 +308,10 @@ typedef struct _GSourceIter
|
|||||||
#define UNLOCK_CONTEXT(context) g_mutex_unlock (&context->mutex)
|
#define UNLOCK_CONTEXT(context) g_mutex_unlock (&context->mutex)
|
||||||
#define G_THREAD_SELF g_thread_self ()
|
#define G_THREAD_SELF g_thread_self ()
|
||||||
|
|
||||||
#define SOURCE_DESTROYED(source) (((source)->flags & G_HOOK_FLAG_ACTIVE) == 0)
|
#define SOURCE_DESTROYED(source) \
|
||||||
#define SOURCE_BLOCKED(source) (((source)->flags & G_SOURCE_BLOCKED) != 0)
|
((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 */
|
/* Forward declarations */
|
||||||
|
|
||||||
@ -930,11 +933,11 @@ g_source_new (GSourceFuncs *source_funcs,
|
|||||||
source = (GSource*) g_malloc0 (struct_size);
|
source = (GSource*) g_malloc0 (struct_size);
|
||||||
source->priv = g_slice_new0 (GSourcePrivate);
|
source->priv = g_slice_new0 (GSourcePrivate);
|
||||||
source->source_funcs = source_funcs;
|
source->source_funcs = source_funcs;
|
||||||
source->ref_count = 1;
|
g_atomic_int_set (&source->ref_count, 1);
|
||||||
|
|
||||||
source->priority = G_PRIORITY_DEFAULT;
|
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;
|
source->priv->ready_time = -1;
|
||||||
|
|
||||||
@ -976,10 +979,14 @@ void
|
|||||||
g_source_set_dispose_function (GSource *source,
|
g_source_set_dispose_function (GSource *source,
|
||||||
GSourceDisposeFunc dispose)
|
GSourceDisposeFunc dispose)
|
||||||
{
|
{
|
||||||
|
gboolean was_unset G_GNUC_UNUSED;
|
||||||
|
|
||||||
g_return_if_fail (source != NULL);
|
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);
|
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 */
|
/* Holds context's lock */
|
||||||
@ -1285,7 +1292,7 @@ g_source_destroy_internal (GSource *source,
|
|||||||
gpointer old_cb_data;
|
gpointer old_cb_data;
|
||||||
GSourceCallbackFuncs *old_cb_funcs;
|
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_data = source->callback_data;
|
||||||
old_cb_funcs = source->callback_funcs;
|
old_cb_funcs = source->callback_funcs;
|
||||||
@ -1359,7 +1366,7 @@ g_source_destroy (GSource *source)
|
|||||||
if (context)
|
if (context)
|
||||||
g_source_destroy_internal (source, context, FALSE);
|
g_source_destroy_internal (source, context, FALSE);
|
||||||
else
|
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);
|
LOCK_CONTEXT (context);
|
||||||
|
|
||||||
if (can_recurse)
|
if (can_recurse)
|
||||||
source->flags |= G_SOURCE_CAN_RECURSE;
|
g_atomic_int_or (&source->flags, G_SOURCE_CAN_RECURSE);
|
||||||
else
|
else
|
||||||
source->flags &= ~G_SOURCE_CAN_RECURSE;
|
g_atomic_int_and (&source->flags, ~G_SOURCE_CAN_RECURSE);
|
||||||
|
|
||||||
if (context)
|
if (context)
|
||||||
UNLOCK_CONTEXT (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 (source != NULL, FALSE);
|
||||||
g_return_val_if_fail (g_atomic_int_get (&source->ref_count) > 0, 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
|
static void
|
||||||
@ -2246,11 +2253,13 @@ retry_beginning:
|
|||||||
if (old_ref == 1)
|
if (old_ref == 1)
|
||||||
{
|
{
|
||||||
/* If there's a dispose function, call this first */
|
/* 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)
|
if (context)
|
||||||
UNLOCK_CONTEXT (context);
|
UNLOCK_CONTEXT (context);
|
||||||
source->priv->dispose (source);
|
dispose_func (source);
|
||||||
if (context)
|
if (context)
|
||||||
LOCK_CONTEXT (context);
|
LOCK_CONTEXT (context);
|
||||||
}
|
}
|
||||||
@ -3267,7 +3276,7 @@ block_source (GSource *source)
|
|||||||
|
|
||||||
g_return_if_fail (!SOURCE_BLOCKED (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)
|
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_BLOCKED (source)); /* Source already unblocked */
|
||||||
g_return_if_fail (!SOURCE_DESTROYED (source));
|
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;
|
tmp_list = source->poll_fds;
|
||||||
while (tmp_list)
|
while (tmp_list)
|
||||||
@ -3339,7 +3348,7 @@ g_main_dispatch (GMainContext *context)
|
|||||||
context->pending_dispatches->pdata[i] = NULL;
|
context->pending_dispatches->pdata[i] = NULL;
|
||||||
g_assert (source);
|
g_assert (source);
|
||||||
|
|
||||||
source->flags &= ~G_SOURCE_READY;
|
g_atomic_int_and (&source->flags, ~G_SOURCE_READY);
|
||||||
|
|
||||||
if (!SOURCE_DESTROYED (source))
|
if (!SOURCE_DESTROYED (source))
|
||||||
{
|
{
|
||||||
@ -3363,11 +3372,12 @@ g_main_dispatch (GMainContext *context)
|
|||||||
if (cb_funcs)
|
if (cb_funcs)
|
||||||
cb_funcs->ref (cb_data);
|
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);
|
block_source (source);
|
||||||
|
|
||||||
was_in_call = source->flags & G_HOOK_FLAG_IN_CALL;
|
was_in_call = g_atomic_int_or (&source->flags,
|
||||||
source->flags |= G_HOOK_FLAG_IN_CALL;
|
(GSourceFlags) G_HOOK_FLAG_IN_CALL) &
|
||||||
|
G_HOOK_FLAG_IN_CALL;
|
||||||
|
|
||||||
if (cb_funcs)
|
if (cb_funcs)
|
||||||
cb_funcs->get (cb_data, source, &callback, &user_data);
|
cb_funcs->get (cb_data, source, &callback, &user_data);
|
||||||
@ -3404,7 +3414,7 @@ g_main_dispatch (GMainContext *context)
|
|||||||
LOCK_CONTEXT (context);
|
LOCK_CONTEXT (context);
|
||||||
|
|
||||||
if (!was_in_call)
|
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);
|
unblock_source (source);
|
||||||
@ -3773,7 +3783,7 @@ g_main_context_prepare_unlocked (GMainContext *context,
|
|||||||
if ((n_ready > 0) && (source->priority > current_priority))
|
if ((n_ready > 0) && (source->priority > current_priority))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!(source->flags & G_SOURCE_READY))
|
if (!(g_atomic_int_get (&source->flags) & G_SOURCE_READY))
|
||||||
{
|
{
|
||||||
gboolean result;
|
gboolean result;
|
||||||
gboolean (* prepare) (GSource *source,
|
gboolean (* prepare) (GSource *source,
|
||||||
@ -3834,13 +3844,13 @@ g_main_context_prepare_unlocked (GMainContext *context,
|
|||||||
|
|
||||||
while (ready_source)
|
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;
|
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++;
|
n_ready++;
|
||||||
current_priority = source->priority;
|
current_priority = source->priority;
|
||||||
@ -4106,7 +4116,7 @@ g_main_context_check_unlocked (GMainContext *context,
|
|||||||
if ((n_ready > 0) && (source->priority > max_priority))
|
if ((n_ready > 0) && (source->priority > max_priority))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!(source->flags & G_SOURCE_READY))
|
if (!(g_atomic_int_get (&source->flags) & G_SOURCE_READY))
|
||||||
{
|
{
|
||||||
gboolean result;
|
gboolean result;
|
||||||
gboolean (* check) (GSource *source);
|
gboolean (* check) (GSource *source);
|
||||||
@ -4177,13 +4187,13 @@ g_main_context_check_unlocked (GMainContext *context,
|
|||||||
|
|
||||||
while (ready_source)
|
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;
|
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_source_ref (source);
|
||||||
g_ptr_array_add (context->pending_dispatches, source);
|
g_ptr_array_add (context->pending_dispatches, source);
|
||||||
|
@ -275,7 +275,7 @@ struct _GSource
|
|||||||
GMainContext *context;
|
GMainContext *context;
|
||||||
|
|
||||||
gint priority;
|
gint priority;
|
||||||
guint flags;
|
guint flags; /* (atomic) */
|
||||||
guint source_id;
|
guint source_id;
|
||||||
|
|
||||||
GSList *poll_fds;
|
GSList *poll_fds;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user