From 258f63b8ac9a39e313b025f014e504dd56e8bb20 Mon Sep 17 00:00:00 2001 From: Ognyan Tonchev Date: Mon, 9 Sep 2013 11:05:26 +0200 Subject: [PATCH] thread-pool: Add cleanup to wait for the threadpool to finish Also fix race condition if two threads are asking for the first thread from the thread pool at once. This would case two internal GThreadPools to be created. https://bugzilla.gnome.org/show_bug.cgi?id=707753 --- gst/rtsp-server/rtsp-thread-pool.c | 32 ++++++++++++++++++++++++++++++-- gst/rtsp-server/rtsp-thread-pool.h | 1 + 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/gst/rtsp-server/rtsp-thread-pool.c b/gst/rtsp-server/rtsp-thread-pool.c index 87a035f..5907acc 100644 --- a/gst/rtsp-server/rtsp-thread-pool.c +++ b/gst/rtsp-server/rtsp-thread-pool.c @@ -229,8 +229,6 @@ gst_rtsp_thread_pool_class_init (GstRTSPThreadPoolClass * klass) klass->get_thread = default_get_thread; - klass->pool = g_thread_pool_new ((GFunc) do_loop, klass, -1, FALSE, NULL); - GST_DEBUG_CATEGORY_INIT (rtsp_thread_pool_debug, "rtspthreadpool", 0, "GstRTSPThreadPool"); @@ -503,8 +501,38 @@ gst_rtsp_thread_pool_get_thread (GstRTSPThreadPool * pool, klass = GST_RTSP_THREAD_POOL_GET_CLASS (pool); + /* We want to be thread safe as there might be 2 threads wanting to get new + * #GstRTSPThread at the same time + */ + if (G_UNLIKELY (!g_atomic_pointer_get (&klass->pool))) { + GThreadPool *t_pool; + t_pool = g_thread_pool_new ((GFunc) do_loop, klass, -1, FALSE, NULL); + if (!g_atomic_pointer_compare_and_exchange (&klass->pool, NULL, t_pool)) + g_thread_pool_free (t_pool, FALSE, TRUE); + } + if (klass->get_thread) result = klass->get_thread (pool, type, ctx); return result; } + +/** + * gst_rtsp_thread_pool_cleanup: + * + * Wait for all tasks to be stopped and free all allocated resources. This is + * mainly used in test suites to ensure proper cleanup of internal data + * structures. + */ +void +gst_rtsp_thread_pool_cleanup (void) +{ + GstRTSPThreadPoolClass *klass; + + klass = GST_RTSP_THREAD_POOL_CLASS ( + g_type_class_peek (gst_rtsp_thread_pool_get_type ())); + if (klass->pool != NULL) { + g_thread_pool_free (klass->pool, FALSE, TRUE); + klass->pool = NULL; + } +} diff --git a/gst/rtsp-server/rtsp-thread-pool.h b/gst/rtsp-server/rtsp-thread-pool.h index 148e73f..8165125 100644 --- a/gst/rtsp-server/rtsp-thread-pool.h +++ b/gst/rtsp-server/rtsp-thread-pool.h @@ -169,6 +169,7 @@ gint gst_rtsp_thread_pool_get_max_threads (GstRTSPThreadPool * po GstRTSPThread * gst_rtsp_thread_pool_get_thread (GstRTSPThreadPool *pool, GstRTSPThreadType type, GstRTSPContext *ctx); +void gst_rtsp_thread_pool_cleanup (void); G_END_DECLS #endif /* __GST_RTSP_THREAD_POOL_H__ */ -- 2.7.4