[glib/wip/gcleanup] gthreadpool: Initial support for cleaning up thread pool



commit 147780f74e744cb135780adb1c0cd2e281f67155
Author: Stef Walter <stefw gnome org>
Date:   Thu Nov 7 22:40:04 2013 +0100

    gthreadpool: Initial support for cleaning up thread pool
    
    WIP
    
    Some work needed to figure out better way to stop unused threads.

 glib/gthreadpool.c |   34 +++++++++++++++++++++++++++++++++-
 1 files changed, 33 insertions(+), 1 deletions(-)
---
diff --git a/glib/gthreadpool.c b/glib/gthreadpool.c
index 78684ab..f8b4ae1 100644
--- a/glib/gthreadpool.c
+++ b/glib/gthreadpool.c
@@ -107,6 +107,8 @@ struct _GRealThreadPool
 static const gpointer wakeup_thread_marker = (gpointer) &g_thread_pool_new;
 static gint wakeup_thread_serial = 0;
 
+static gint alive_threads = 0;
+
 /* Here all unused threads are waiting  */
 static GAsyncQueue *unused_thread_queue = NULL;
 static gint unused_threads = 0;
@@ -289,6 +291,8 @@ g_thread_pool_thread_proxy (gpointer data)
 
   DEBUG_MSG (("thread %p started for pool %p.", g_thread_self (), pool));
 
+  g_atomic_int_add (&alive_threads, 1);
+
   g_async_queue_lock (pool->queue);
 
   while (TRUE)
@@ -378,6 +382,8 @@ g_thread_pool_thread_proxy (gpointer data)
         }
     }
 
+  g_atomic_int_add (&alive_threads, -1);
+
   return NULL;
 }
 
@@ -422,6 +428,23 @@ g_thread_pool_start_thread (GRealThreadPool  *pool,
   return TRUE;
 }
 
+static void
+stop_all_unused_threads (void)
+{
+  /*
+   * FIXME: Making sure that no threads are left behind requires
+   *        significant changes to the current implementation,
+   *        so for now we'll signal and always wait 10 ms,
+   *        allowing any threads that were already in the process
+   *        of shutting down to execute their last instructions... ICK!
+   */
+  g_thread_pool_set_max_unused_threads (0);
+  while (alive_threads > 0)
+    g_usleep (10000);
+
+  g_async_queue_unref (unused_thread_queue);
+}
+
 /**
  * g_thread_pool_new:
  * @func: a function to execute in the threads of the new thread pool
@@ -488,7 +511,10 @@ g_thread_pool_new (GFunc      func,
 
   G_LOCK (init);
   if (!unused_thread_queue)
+    {
       unused_thread_queue = g_async_queue_new ();
+      G_CLEANUP_FUNC (stop_all_unused_threads);
+    }
   G_UNLOCK (init);
 
   if (retval->pool.exclusive)
@@ -818,8 +844,14 @@ g_thread_pool_wakeup_and_stop_all (GRealThreadPool *pool)
 
   pool->immediate = TRUE;
 
+  /*
+   * So here we're sending bogus data to the pool threads, which
+   * should cause them each to wake up, and check the above
+   * pool->imediate condition. However we don't want that
+   * data to be sorted (since it'll crash the sorter).
+   */
   for (i = 0; i < pool->num_threads; i++)
-    g_thread_pool_queue_push_unlocked (pool, GUINT_TO_POINTER (1));
+    g_async_queue_push_unlocked (pool->queue, GUINT_TO_POINTER (1));
 }
 
 /**


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