When dispatching a source that is !CAN_RECURSE, temporarily remove any
authorOwen Taylor <otaylor@redhat.com>
Fri, 6 Jun 2003 03:54:03 +0000 (03:54 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Fri, 6 Jun 2003 03:54:03 +0000 (03:54 +0000)
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)

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
glib/gmain.c

index b6d1fe8..7fb9790 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+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
index b6d1fe8..7fb9790 100644 (file)
@@ -1,3 +1,17 @@
+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
index b6d1fe8..7fb9790 100644 (file)
@@ -1,3 +1,17 @@
+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
index b6d1fe8..7fb9790 100644 (file)
@@ -1,3 +1,17 @@
+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
index b6d1fe8..7fb9790 100644 (file)
@@ -1,3 +1,17 @@
+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
index b6d1fe8..7fb9790 100644 (file)
@@ -1,3 +1,17 @@
+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
index 4a66ee0..45ecb5f 100644 (file)
@@ -175,6 +175,8 @@ struct _GPollRec
 #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 {                                           \
@@ -887,14 +889,17 @@ g_source_destroy_internal (GSource      *source,
          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);
     }
 
@@ -1000,7 +1005,8 @@ g_source_add_poll (GSource *source,
 
   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);
     }
 }
@@ -1032,7 +1038,8 @@ g_source_remove_poll (GSource *source,
 
   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);
     }
 }
@@ -1186,16 +1193,22 @@ g_source_set_priority (GSource  *source,
 
   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);
@@ -1622,6 +1635,43 @@ g_get_current_time (GTimeVal *result)
 
 /* 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)
@@ -1657,6 +1707,9 @@ 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;
 
@@ -1676,6 +1729,10 @@ 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))
+           unblock_source (source);
+         
          /* Note: this depends on the fact that we can't switch
           * sources from one main context to another
           */
@@ -1964,7 +2021,7 @@ g_main_context_prepare (GMainContext *context,
          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))
@@ -2152,7 +2209,7 @@ g_main_context_check (GMainContext *context,
          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))