+Thu Jun 5 23:40:31 2003 Owen Taylor <otaylor@redhat.com>
+
+ * glib/gmain.c: When dispatching a source that is
+ !CAN_RECURSE, temporarily remove any file descriptors
+ that that source has registered from the main loop, to keep
+ recursive main loops from busy-waiting if input
+ becomes available on one of those file descriptors.
+ (#112222, Christian Krause)
+
+ * glib/gmain.c (g_source_set_priority): Properly
+ remove the source from the context's source list
+ and reinsert it sorted, rather than simply setting
+ source->next/prev to NULL! (#114274)
+
2003-06-06 Matthias Clasen <maclas@gmx.de>
* glib/gstring.c (g_string_append_printf_internal): Use
+Thu Jun 5 23:40:31 2003 Owen Taylor <otaylor@redhat.com>
+
+ * glib/gmain.c: When dispatching a source that is
+ !CAN_RECURSE, temporarily remove any file descriptors
+ that that source has registered from the main loop, to keep
+ recursive main loops from busy-waiting if input
+ becomes available on one of those file descriptors.
+ (#112222, Christian Krause)
+
+ * glib/gmain.c (g_source_set_priority): Properly
+ remove the source from the context's source list
+ and reinsert it sorted, rather than simply setting
+ source->next/prev to NULL! (#114274)
+
2003-06-06 Matthias Clasen <maclas@gmx.de>
* glib/gstring.c (g_string_append_printf_internal): Use
+Thu Jun 5 23:40:31 2003 Owen Taylor <otaylor@redhat.com>
+
+ * glib/gmain.c: When dispatching a source that is
+ !CAN_RECURSE, temporarily remove any file descriptors
+ that that source has registered from the main loop, to keep
+ recursive main loops from busy-waiting if input
+ becomes available on one of those file descriptors.
+ (#112222, Christian Krause)
+
+ * glib/gmain.c (g_source_set_priority): Properly
+ remove the source from the context's source list
+ and reinsert it sorted, rather than simply setting
+ source->next/prev to NULL! (#114274)
+
2003-06-06 Matthias Clasen <maclas@gmx.de>
* glib/gstring.c (g_string_append_printf_internal): Use
+Thu Jun 5 23:40:31 2003 Owen Taylor <otaylor@redhat.com>
+
+ * glib/gmain.c: When dispatching a source that is
+ !CAN_RECURSE, temporarily remove any file descriptors
+ that that source has registered from the main loop, to keep
+ recursive main loops from busy-waiting if input
+ becomes available on one of those file descriptors.
+ (#112222, Christian Krause)
+
+ * glib/gmain.c (g_source_set_priority): Properly
+ remove the source from the context's source list
+ and reinsert it sorted, rather than simply setting
+ source->next/prev to NULL! (#114274)
+
2003-06-06 Matthias Clasen <maclas@gmx.de>
* glib/gstring.c (g_string_append_printf_internal): Use
+Thu Jun 5 23:40:31 2003 Owen Taylor <otaylor@redhat.com>
+
+ * glib/gmain.c: When dispatching a source that is
+ !CAN_RECURSE, temporarily remove any file descriptors
+ that that source has registered from the main loop, to keep
+ recursive main loops from busy-waiting if input
+ becomes available on one of those file descriptors.
+ (#112222, Christian Krause)
+
+ * glib/gmain.c (g_source_set_priority): Properly
+ remove the source from the context's source list
+ and reinsert it sorted, rather than simply setting
+ source->next/prev to NULL! (#114274)
+
2003-06-06 Matthias Clasen <maclas@gmx.de>
* glib/gstring.c (g_string_append_printf_internal): Use
+Thu Jun 5 23:40:31 2003 Owen Taylor <otaylor@redhat.com>
+
+ * glib/gmain.c: When dispatching a source that is
+ !CAN_RECURSE, temporarily remove any file descriptors
+ that that source has registered from the main loop, to keep
+ recursive main loops from busy-waiting if input
+ becomes available on one of those file descriptors.
+ (#112222, Christian Krause)
+
+ * glib/gmain.c (g_source_set_priority): Properly
+ remove the source from the context's source list
+ and reinsert it sorted, rather than simply setting
+ source->next/prev to NULL! (#114274)
+
2003-06-06 Matthias Clasen <maclas@gmx.de>
* glib/gstring.c (g_string_append_printf_internal): Use
#endif
#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_UNREF(source, context) \
G_STMT_START { \
old_cb_funcs->unref (old_cb_data);
LOCK_CONTEXT (context);
}
-
- tmp_list = source->poll_fds;
- while (tmp_list)
+
+ if (!SOURCE_BLOCKED (source))
{
- g_main_context_remove_poll_unlocked (context, tmp_list->data);
- tmp_list = tmp_list->next;
+ tmp_list = source->poll_fds;
+ while (tmp_list)
+ {
+ g_main_context_remove_poll_unlocked (context, tmp_list->data);
+ tmp_list = tmp_list->next;
+ }
}
-
+
g_source_unref_internal (source, context, TRUE);
}
if (context)
{
- g_main_context_add_poll_unlocked (context, source->priority, fd);
+ if (!SOURCE_BLOCKED (source))
+ g_main_context_add_poll_unlocked (context, source->priority, fd);
UNLOCK_CONTEXT (context);
}
}
if (context)
{
- g_main_context_remove_poll_unlocked (context, fd);
+ if (!SOURCE_BLOCKED (source))
+ g_main_context_remove_poll_unlocked (context, fd);
UNLOCK_CONTEXT (context);
}
}
if (context)
{
- source->next = NULL;
- source->prev = NULL;
-
- tmp_list = source->poll_fds;
- while (tmp_list)
+ /* Remove the source from the context's source and then
+ * add it back so it is sorted in the correct plcae
+ */
+ g_source_list_remove (source, source->context);
+ g_source_list_add (source, source->context);
+
+ if (!SOURCE_BLOCKED (source))
{
- g_main_context_remove_poll_unlocked (context, tmp_list->data);
- g_main_context_add_poll_unlocked (context, priority, tmp_list->data);
-
- tmp_list = tmp_list->next;
+ tmp_list = source->poll_fds;
+ while (tmp_list)
+ {
+ g_main_context_remove_poll_unlocked (context, tmp_list->data);
+ g_main_context_add_poll_unlocked (context, priority, tmp_list->data);
+
+ tmp_list = tmp_list->next;
+ }
}
UNLOCK_CONTEXT (source->context);
/* Running the main loop */
+/* Temporarily remove all this source's file descriptors from the
+ * poll(), so that if data comes available for one of the file descriptors
+ * we don't continually spin in the poll()
+ */
+/* HOLDS: source->context's lock */
+void
+block_source (GSource *source)
+{
+ GSList *tmp_list;
+
+ g_return_if_fail (!SOURCE_BLOCKED (source));
+
+ tmp_list = source->poll_fds;
+ while (tmp_list)
+ {
+ g_main_context_remove_poll_unlocked (source->context, tmp_list->data);
+ tmp_list = tmp_list->next;
+ }
+}
+
+/* HOLDS: source->context's lock */
+void
+unblock_source (GSource *source)
+{
+ GSList *tmp_list;
+
+ g_return_if_fail (!SOURCE_BLOCKED (source)); /* Source already unblocked */
+ g_return_if_fail (!SOURCE_DESTROYED (source));
+
+ 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;
+ }
+}
+
/* HOLDS: context's lock */
static void
g_main_dispatch (GMainContext *context)
if (cb_funcs)
cb_funcs->ref (cb_data);
+ if ((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;
if (!was_in_call)
source->flags &= ~G_HOOK_FLAG_IN_CALL;
+ if ((source->flags & G_SOURCE_CAN_RECURSE) == 0 &&
+ !SOURCE_DESTROYED (source))
+ unblock_source (source);
+
/* Note: this depends on the fact that we can't switch
* sources from one main context to another
*/
SOURCE_UNREF (source, context);
break;
}
- if ((source->flags & G_HOOK_FLAG_IN_CALL) && !(source->flags & G_SOURCE_CAN_RECURSE))
+ if (SOURCE_BLOCKED (source))
goto next;
if (!(source->flags & G_SOURCE_READY))
SOURCE_UNREF (source, context);
break;
}
- if ((source->flags & G_HOOK_FLAG_IN_CALL) && !(source->flags & G_SOURCE_CAN_RECURSE))
+ if (SOURCE_BLOCKED (source))
goto next;
if (!(source->flags & G_SOURCE_READY))