[glib/wip/gmain: 2/8] gmain: Only wake up affected contexts on receipt of UNIX signal



commit e602e8389a3ae257936e23257e8e80b8ff5e367f
Author: Colin Walters <walters verbum org>
Date:   Tue Jun 7 13:34:22 2011 -0400

    gmain: Only wake up affected contexts on receipt of UNIX signal
    
    Now that we maintain lists of both UNIX signal watches and SIGCHLD
    handlers, simply iterate over them and wake up their context,
    rather than all contexts.
    
    If your app has 1000 threads but is only watching a subprocess exit
    from the main thread, this saves 999 wakeups.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=652072

 glib/gmain.c |   48 +++++++++++++++++++++---------------------------
 1 files changed, 21 insertions(+), 27 deletions(-)
---
diff --git a/glib/gmain.c b/glib/gmain.c
index 11a2494..dd3446d 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -357,10 +357,9 @@ static void g_main_context_add_poll_unlocked    (GMainContext *context,
 						 GPollFD      *fd);
 static void g_main_context_remove_poll_unlocked (GMainContext *context,
 						 GPollFD      *fd);
+static void g_main_context_wakeup_safe (GMainContext *context);
 static void g_main_context_wakeup_unlocked      (GMainContext *context);
 
-static void _g_main_wake_up_all_contexts        (void);
-
 static gboolean g_timeout_prepare  (GSource     *source,
 				    gint        *timeout);
 static gboolean g_timeout_check    (GSource     *source);
@@ -3771,30 +3770,6 @@ g_main_context_get_poll_func (GMainContext *context)
   return result;
 }
 
-static void
-_g_main_wake_up_all_contexts (void)
-{
-  GSList *list;
-
-  /* We were woken up.  Wake up all other contexts in all other threads */
-  G_LOCK (main_context_list);
-  for (list = main_context_list; list; list = list->next)
-    {
-      GMainContext *context;
-
-      context = list->data;
-      if (g_atomic_int_get (&context->ref_count) > 0)
-	/* Due to racing conditions we can find ref_count == 0, in
-	 * that case, however, the context is still not destroyed
-	 * and no poll can be active, otherwise the ref_count
-	 * wouldn't be 0
-	 */
-	g_main_context_wakeup (context);
-    }
-  G_UNLOCK (main_context_list);
-}
-
-
 /* HOLDS: context's lock */
 /* Wake the main loop up from a poll() */
 static void
@@ -3813,6 +3788,23 @@ g_main_context_wakeup_unlocked (GMainContext *context)
 #endif
 }
 
+/* Called without the context lock in threaded wakeups; due to racing
+ * conditions we can find ref_count == 0, in that case, however, the
+ * context is still not destroyed and no poll can be active, otherwise
+ * the ref_count wouldn't be 0
+ */
+static void
+g_main_context_wakeup_safe (GMainContext *context)
+{
+  if (!context)
+    context = g_main_context_default ();
+  
+  if (g_atomic_int_get (&context->ref_count) <= 0)
+    return;
+
+  g_main_context_wakeup (context);
+}
+
 /**
  * g_main_context_wakeup:
  * @context: a #GMainContext
@@ -4611,6 +4603,7 @@ deliver_unix_signal (int signum)
 	continue;
       
       source->pending = TRUE;
+      g_main_context_wakeup_safe (source->source.context);
     }
   G_UNLOCK (unix_signal_lock);
 }
@@ -4630,6 +4623,8 @@ deliver_sigchld (void)
 	continue;
 
       unix_check_for_child_exited_unlocked (source);
+      if (source->child_exited)
+	g_main_context_wakeup_safe (source->source.context);
     }
   G_UNLOCK (unix_signal_lock);
 }
@@ -4698,7 +4693,6 @@ unix_signal_helper_thread (gpointer data)
 	    deliver_unix_signal (SIGHUP);
 	  if (sigchld_received)
 	    deliver_sigchld ();
-	  _g_main_wake_up_all_contexts ();
 	}
     }
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]