[glib/glib-2-32] gmain: block child sources when blocking the parent
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/glib-2-32] gmain: block child sources when blocking the parent
- Date: Mon, 16 Apr 2012 19:49:53 +0000 (UTC)
commit b1d447bd664bcbc607811c7920b67856d4f551e6
Author: Dan Winship <danw gnome org>
Date: Wed Apr 11 15:21:17 2012 -0400
gmain: block child sources when blocking the parent
When blocking a source that has child sources, we need to consider the
children blocked as well. Otherwise they will still trigger repeatedly
in an inner loop started from the parent source's callback.
https://bugzilla.gnome.org/show_bug.cgi?id=669260
glib/gmain.c | 35 +++++++++++++++++++++++++++++------
1 files changed, 29 insertions(+), 6 deletions(-)
---
diff --git a/glib/gmain.c b/glib/gmain.c
index 68839b5..760f179 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -191,7 +191,8 @@ typedef struct _GSourceCallback GSourceCallback;
typedef enum
{
G_SOURCE_READY = 1 << G_HOOK_FLAG_USER_SHIFT,
- G_SOURCE_CAN_RECURSE = 1 << (G_HOOK_FLAG_USER_SHIFT + 1)
+ G_SOURCE_CAN_RECURSE = 1 << (G_HOOK_FLAG_USER_SHIFT + 1),
+ G_SOURCE_BLOCKED = 1 << (G_HOOK_FLAG_USER_SHIFT + 2)
} GSourceFlags;
typedef struct _GMainWaiter GMainWaiter;
@@ -313,8 +314,7 @@ struct _GSourcePrivate
#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_HOOK_FLAG_IN_CALL) != 0 && \
- ((source)->flags & G_SOURCE_CAN_RECURSE) == 0)
+#define SOURCE_BLOCKED(source) (((source)->flags & G_SOURCE_BLOCKED) != 0)
#define SOURCE_UNREF(source, context) \
G_STMT_START { \
@@ -2426,12 +2426,24 @@ block_source (GSource *source)
g_return_if_fail (!SOURCE_BLOCKED (source));
+ source->flags |= G_SOURCE_BLOCKED;
+
tmp_list = source->poll_fds;
while (tmp_list)
{
g_main_context_remove_poll_unlocked (source->context, tmp_list->data);
tmp_list = tmp_list->next;
}
+
+ if (source->priv && source->priv->child_sources)
+ {
+ tmp_list = source->priv->child_sources;
+ while (tmp_list)
+ {
+ block_source (tmp_list->data);
+ tmp_list = tmp_list->next;
+ }
+ }
}
/* HOLDS: source->context's lock */
@@ -2440,15 +2452,27 @@ unblock_source (GSource *source)
{
GSList *tmp_list;
- 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));
+ source->flags &= ~G_SOURCE_BLOCKED;
+
tmp_list = source->poll_fds;
while (tmp_list)
{
g_main_context_add_poll_unlocked (source->context, source->priority, tmp_list->data);
tmp_list = tmp_list->next;
}
+
+ if (source->priv && source->priv->child_sources)
+ {
+ tmp_list = source->priv->child_sources;
+ while (tmp_list)
+ {
+ unblock_source (tmp_list->data);
+ tmp_list = tmp_list->next;
+ }
+ }
}
/* HOLDS: context's lock */
@@ -2527,8 +2551,7 @@ g_main_dispatch (GMainContext *context)
if (!was_in_call)
source->flags &= ~G_HOOK_FLAG_IN_CALL;
- if ((source->flags & G_SOURCE_CAN_RECURSE) == 0 &&
- !SOURCE_DESTROYED (source))
+ if (SOURCE_BLOCKED (source) && !SOURCE_DESTROYED (source))
unblock_source (source);
/* Note: this depends on the fact that we can't switch
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]