thread: Add destroy notify function for post user data

The destroy notify function can be called on any thread.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This commit is contained in:
Jonas Ådahl 2022-06-04 22:45:17 +02:00
parent 7c9d4b8c7c
commit e4a8fc93a1
5 changed files with 34 additions and 14 deletions

View File

@ -62,6 +62,7 @@ struct _MetaThreadTask
{
MetaThreadTaskFunc func;
gpointer user_data;
GDestroyNotify user_data_destroy;
MetaThreadTaskFeedbackFunc feedback_func;
gpointer feedback_user_data;
@ -269,6 +270,7 @@ meta_thread_impl_get_main_context (MetaThreadImpl *thread_impl)
MetaThreadTask *
meta_thread_task_new (MetaThreadTaskFunc func,
gpointer user_data,
GDestroyNotify user_data_destroy,
MetaThreadTaskFeedbackFunc feedback_func,
gpointer feedback_user_data,
GMainContext *feedback_main_context)
@ -279,6 +281,7 @@ meta_thread_task_new (MetaThreadTaskFunc func,
*task = (MetaThreadTask) {
.func = func,
.user_data = user_data,
.user_data_destroy = user_data_destroy,
.feedback_func = feedback_func,
.feedback_user_data = feedback_user_data,
.feedback_main_context = feedback_main_context,
@ -290,6 +293,8 @@ meta_thread_task_new (MetaThreadTaskFunc func,
void
meta_thread_task_free (MetaThreadTask *task)
{
if (task->user_data_destroy)
task->user_data_destroy (task->user_data);
g_clear_error (&task->error);
g_free (task);
}

View File

@ -75,6 +75,7 @@ gboolean meta_thread_impl_is_in_impl (MetaThreadImpl *thread_impl);
MetaThreadTask * meta_thread_task_new (MetaThreadTaskFunc func,
gpointer user_data,
GDestroyNotify user_data_destroy,
MetaThreadTaskFeedbackFunc feedback_func,
gpointer feedback_user_data,
GMainContext *feedback_main_context);

View File

@ -587,7 +587,7 @@ run_impl_task_sync_user (MetaThread *thread,
MetaThreadTask *task;
MetaSyncTaskData data = { 0 };
task = meta_thread_task_new (func, user_data,
task = meta_thread_task_new (func, user_data, NULL,
sync_task_done_user_in_impl, &data,
meta_thread_impl_get_main_context (priv->impl));
meta_thread_impl_queue_task (priv->impl, task);
@ -636,7 +636,7 @@ run_impl_task_sync_kernel (MetaThread *thread,
g_mutex_lock (&data.kernel.mutex);
priv->waiting_for_impl_task = TRUE;
task = meta_thread_task_new (func, user_data,
task = meta_thread_task_new (func, user_data, NULL,
sync_task_done_kernel_in_impl, &data,
meta_thread_impl_get_main_context (priv->impl));
meta_thread_impl_queue_task (priv->impl, task);
@ -683,13 +683,14 @@ void
meta_thread_post_impl_task (MetaThread *thread,
MetaThreadTaskFunc func,
gpointer user_data,
GDestroyNotify user_data_destroy,
MetaThreadTaskFeedbackFunc feedback_func,
gpointer feedback_user_data)
{
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
MetaThreadTask *task;
task = meta_thread_task_new (func, user_data,
task = meta_thread_task_new (func, user_data, user_data_destroy,
feedback_func, feedback_user_data,
g_main_context_get_thread_default ());
meta_thread_impl_queue_task (priv->impl, task);

View File

@ -82,6 +82,7 @@ META_EXPORT_TEST
void meta_thread_post_impl_task (MetaThread *thread,
MetaThreadTaskFunc func,
gpointer user_data,
GDestroyNotify user_data_destroy,
MetaThreadTaskFeedbackFunc feedback_func,
gpointer feedback_user_data);

View File

@ -243,6 +243,18 @@ async_func (MetaThreadImpl *thread_impl,
return GINT_TO_POINTER (TRUE);
}
static void
async_destroy (gpointer user_data)
{
AsyncData *async_data = user_data;
g_mutex_lock (&async_data->mutex);
g_assert_cmpint (async_data->state, ==, 2);
async_data->state = 3;
g_main_loop_quit (async_data->loop);
g_mutex_unlock (&async_data->mutex);
}
static void
async_feedback_func (gpointer retval,
const GError *error,
@ -255,7 +267,6 @@ async_feedback_func (gpointer retval,
g_mutex_lock (&async_data->mutex);
g_assert_cmpint (async_data->state, ==, 1);
async_data->state = 2;
g_main_loop_quit (async_data->loop);
g_mutex_unlock (&async_data->mutex);
}
@ -606,7 +617,8 @@ non_default_callback_thread_func (gpointer user_data)
callback_data->thread_main_context);
meta_thread_post_impl_task (callback_data->thread,
queue_non_default_callback_func, callback_data,
queue_non_default_callback_func,
callback_data, NULL,
non_default_thread_feedback_func,
callback_data);
@ -701,13 +713,13 @@ run_thread_tests (MetaThread *thread)
async_data.thread = thread;
async_data.loop = g_main_loop_new (NULL, FALSE);
g_mutex_lock (&async_data.mutex);
meta_thread_post_impl_task (thread, async_func, &async_data,
meta_thread_post_impl_task (thread, async_func, &async_data, async_destroy,
async_feedback_func, &async_data);
g_assert_cmpint (async_data.state, ==, 0);
g_mutex_unlock (&async_data.mutex);
g_main_loop_run (async_data.loop);
g_mutex_lock (&async_data.mutex);
g_assert_cmpint (async_data.state, ==, 2);
g_assert_cmpint (async_data.state, ==, 3);
g_mutex_unlock (&async_data.mutex);
g_main_loop_unref (async_data.loop);
g_mutex_clear (&async_data.mutex);
@ -719,11 +731,11 @@ run_thread_tests (MetaThread *thread)
async_data.thread = thread;
async_data.loop = g_main_loop_new (NULL, FALSE);
g_mutex_lock (&async_data.mutex);
meta_thread_post_impl_task (thread, multiple_async_func1, &async_data,
meta_thread_post_impl_task (thread, multiple_async_func1, &async_data, NULL,
multiple_async_feedback_func1, &async_data);
meta_thread_post_impl_task (thread, multiple_async_func2, &async_data,
meta_thread_post_impl_task (thread, multiple_async_func2, &async_data, NULL,
multiple_async_feedback_func2, &async_data);
meta_thread_post_impl_task (thread, multiple_async_func3, &async_data,
meta_thread_post_impl_task (thread, multiple_async_func3, &async_data, NULL,
multiple_async_feedback_func3, &async_data);
g_assert_cmpint (async_data.state, ==, 0);
g_mutex_unlock (&async_data.mutex);
@ -740,7 +752,7 @@ run_thread_tests (MetaThread *thread)
g_mutex_init (&mixed_data.mutex);
mixed_data.thread = thread;
g_mutex_lock (&mixed_data.mutex);
meta_thread_post_impl_task (thread, mixed_async_func, &mixed_data,
meta_thread_post_impl_task (thread, mixed_async_func, &mixed_data, NULL,
mixed_async_feedback_func, &mixed_data);
g_assert_cmpint (mixed_data.state, ==, 0);
g_mutex_unlock (&mixed_data.mutex);
@ -780,7 +792,7 @@ run_thread_tests (MetaThread *thread)
g_mutex_unlock (&flush_data1.init_mutex);
meta_thread_post_impl_task (thread,
queue_slow_callback,
&flush_data1,
&flush_data1, NULL,
quit_main_loop_feedback_func,
&loop_user);
flush_data2 = (FlushData) {
@ -798,7 +810,7 @@ run_thread_tests (MetaThread *thread)
g_mutex_unlock (&flush_data2.init_mutex);
meta_thread_post_impl_task (thread,
queue_slow_callback,
&flush_data2,
&flush_data2, NULL,
quit_main_loop_feedback_func,
&loop_user);
@ -918,7 +930,7 @@ meta_test_thread_late_callbacks_common (MetaThreadType thread_type)
g_assert_nonnull (thread);
g_assert_null (error);
meta_thread_post_impl_task (thread, late_callback, &done, NULL, NULL);
meta_thread_post_impl_task (thread, late_callback, &done, NULL, NULL, NULL);
g_object_unref (thread);
g_assert_null (thread);