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
This commit is contained in:
nitinosiris 2021-06-26 16:08:42 +05:30
parent d4ed690120
commit 75db4883fc
4 changed files with 97 additions and 1 deletions

View File

@ -1171,6 +1171,7 @@ g_once_init_enter_impl
<FILE>thread_pools</FILE> <FILE>thread_pools</FILE>
GThreadPool GThreadPool
g_thread_pool_new g_thread_pool_new
g_thread_pool_new_full
g_thread_pool_push g_thread_pool_push
g_thread_pool_set_max_threads g_thread_pool_set_max_threads
g_thread_pool_get_max_threads g_thread_pool_get_max_threads

View File

@ -558,6 +558,38 @@ g_thread_pool_new (GFunc func,
gint max_threads, gint max_threads,
gboolean exclusive, gboolean exclusive,
GError **error) 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; GRealThreadPool *retval;
G_LOCK_DEFINE_STATIC (init); G_LOCK_DEFINE_STATIC (init);
@ -571,7 +603,7 @@ g_thread_pool_new (GFunc func,
retval->pool.func = func; retval->pool.func = func;
retval->pool.user_data = user_data; retval->pool.user_data = user_data;
retval->pool.exclusive = exclusive; 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); g_cond_init (&retval->cond);
retval->max_threads = max_threads; retval->max_threads = max_threads;
retval->num_threads = 0; retval->num_threads = 0;

View File

@ -51,6 +51,13 @@ GThreadPool * g_thread_pool_new (GFunc func,
gint max_threads, gint max_threads,
gboolean exclusive, gboolean exclusive,
GError **error); 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 GLIB_AVAILABLE_IN_ALL
void g_thread_pool_free (GThreadPool *pool, void g_thread_pool_free (GThreadPool *pool,
gboolean immediate, gboolean immediate,

View File

@ -87,6 +87,12 @@ dummy_pool_func (gpointer data, gpointer user_data)
g_assert_true (data == GUINT_TO_POINTER (123)); g_assert_true (data == GUINT_TO_POINTER (123));
} }
static void
dummy_pool_func_full (gpointer data, gpointer user_data)
{
g_assert_true (data == user_data);
}
static void static void
test_create_first_pool (gconstpointer shared_first) test_create_first_pool (gconstpointer shared_first)
{ {
@ -142,6 +148,55 @@ test_create_first_pool (gconstpointer shared_first)
g_thread_pool_free (pool, TRUE, TRUE); 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 int
main (int argc, char *argv[]) main (int argc, char *argv[])
{ {
@ -150,6 +205,7 @@ main (int argc, char *argv[])
g_test_add_data_func ("/thread_pool/shared", GINT_TO_POINTER (TRUE), test_simple); 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/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_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); g_test_add_data_func ("/thread_pool/create_exclusive_after_shared", GINT_TO_POINTER (TRUE), test_create_first_pool);
return g_test_run (); return g_test_run ();