GThreadPool: Add g_thread_pool_new_full()
g_thread_pool_new_full() is similar to g_thread_pool_new()
but with GDestroyNotify argument.
Closes #121
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index 863dc5a..4060412 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -1171,6 +1171,7 @@
<FILE>thread_pools</FILE>
GThreadPool
g_thread_pool_new
+g_thread_pool_new_full
g_thread_pool_push
g_thread_pool_set_max_threads
g_thread_pool_get_max_threads
diff --git a/glib/gthreadpool.c b/glib/gthreadpool.c
index 305152a..15d5d4e 100644
--- a/glib/gthreadpool.c
+++ b/glib/gthreadpool.c
@@ -559,6 +559,38 @@
gboolean exclusive,
GError **error)
{
+ return g_thread_pool_new_full (func, user_data, NULL, max_threads, exclusive, error);
+}
+
+/**
+ * g_thread_pool_new_full:
+ * @func: a function to execute in the threads of the new thread pool
+ * @user_data: user data that is handed over to @func every time it
+ * is called
+ * @item_free_func: (nullable): used to pass as a free function to
+ * g_async_queue_new_full()
+ * @max_threads: the maximal number of threads to execute concurrently
+ * in the new thread pool, `-1` means no limit
+ * @exclusive: should this thread pool be exclusive?
+ * @error: return location for error, or %NULL
+ *
+ * This function creates a new thread pool similar to g_thread_pool_new()
+ * but allowing @item_free_func to be specified to free the data passed
+ * to g_thread_pool_push() in the case that the #GThreadPool is stopped
+ * and freed before all tasks have been executed.
+ *
+ * Returns: (transfer full): the new #GThreadPool
+ *
+ * Since: 2.70
+ */
+GThreadPool *
+g_thread_pool_new_full (GFunc func,
+ gpointer user_data,
+ GDestroyNotify item_free_func,
+ gint max_threads,
+ gboolean exclusive,
+ GError **error)
+{
GRealThreadPool *retval;
G_LOCK_DEFINE_STATIC (init);
@@ -571,7 +603,7 @@
retval->pool.func = func;
retval->pool.user_data = user_data;
retval->pool.exclusive = exclusive;
- retval->queue = g_async_queue_new ();
+ retval->queue = g_async_queue_new_full (item_free_func);
g_cond_init (&retval->cond);
retval->max_threads = max_threads;
retval->num_threads = 0;
diff --git a/glib/gthreadpool.h b/glib/gthreadpool.h
index 11c3d1d..f2501b8 100644
--- a/glib/gthreadpool.h
+++ b/glib/gthreadpool.h
@@ -51,6 +51,13 @@
gint max_threads,
gboolean exclusive,
GError **error);
+GLIB_AVAILABLE_IN_2_70
+GThreadPool * g_thread_pool_new_full (GFunc func,
+ gpointer user_data,
+ GDestroyNotify item_free_func,
+ gint max_threads,
+ gboolean exclusive,
+ GError **error);
GLIB_AVAILABLE_IN_ALL
void g_thread_pool_free (GThreadPool *pool,
gboolean immediate,
diff --git a/glib/tests/thread-pool.c b/glib/tests/thread-pool.c
index 703da5d..50a72a6 100644
--- a/glib/tests/thread-pool.c
+++ b/glib/tests/thread-pool.c
@@ -88,6 +88,12 @@
}
static void
+dummy_pool_func_full (gpointer data, gpointer user_data)
+{
+ g_assert_true (data == user_data);
+}
+
+static void
test_create_first_pool (gconstpointer shared_first)
{
GThreadPool *pool;
@@ -142,6 +148,55 @@
g_thread_pool_free (pool, TRUE, TRUE);
}
+static void
+free_func (gpointer user_data)
+{
+ gboolean *free_func_called = user_data;
+ *free_func_called = TRUE;
+}
+
+static void
+test_thread_pool_full (gconstpointer shared_first)
+{
+ GThreadPool *pool;
+ gboolean free_func_called = FALSE;
+ GError *err = NULL;
+ gboolean success;
+
+ g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/121");
+
+ g_thread_pool_set_max_unused_threads (0);
+
+ if (GPOINTER_TO_INT (shared_first))
+ pool = g_thread_pool_new_full (dummy_pool_func_full, &free_func_called, free_func, -1, FALSE, &err);
+ else
+ pool = g_thread_pool_new_full (dummy_pool_func_full, &free_func_called, free_func, 2, TRUE, &err);
+ g_assert_no_error (err);
+ g_assert_nonnull (pool);
+
+ success = g_thread_pool_push (pool, &free_func_called, &err);
+ g_assert_no_error (err);
+ g_assert_true (success);
+
+ g_thread_pool_free (pool, TRUE, TRUE);
+ g_assert_true (free_func_called);
+
+ free_func_called = FALSE;
+ if (GPOINTER_TO_INT (shared_first))
+ pool = g_thread_pool_new_full (dummy_pool_func_full, &free_func_called, free_func, 2, TRUE, &err);
+ else
+ pool = g_thread_pool_new_full (dummy_pool_func_full, &free_func_called, free_func, -1, FALSE, &err);
+ g_assert_no_error (err);
+ g_assert_nonnull (pool);
+
+ success = g_thread_pool_push (pool, &free_func_called, &err);
+ g_assert_no_error (err);
+ g_assert_true (success);
+
+ g_thread_pool_free (pool, TRUE, TRUE);
+ g_assert_true (free_func_called);
+}
+
int
main (int argc, char *argv[])
{
@@ -150,6 +205,7 @@
g_test_add_data_func ("/thread_pool/shared", GINT_TO_POINTER (TRUE), test_simple);
g_test_add_data_func ("/thread_pool/exclusive", GINT_TO_POINTER (FALSE), test_simple);
g_test_add_data_func ("/thread_pool/create_shared_after_exclusive", GINT_TO_POINTER (FALSE), test_create_first_pool);
+ g_test_add_data_func ("/thread_pool/create_full", GINT_TO_POINTER (FALSE), test_thread_pool_full);
g_test_add_data_func ("/thread_pool/create_exclusive_after_shared", GINT_TO_POINTER (TRUE), test_create_first_pool);
return g_test_run ();