mirror of
https://github.com/brl/mutter.git
synced 2024-11-29 19:40:43 -05:00
thread: Make it possible to run sync tasks from any thread
When a task is posted from a non-main thread, a user thread still needs to go via the queue and be signalled using the condition, just as if it was a kernel thread. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This commit is contained in:
parent
d77b5935cd
commit
1350b5e260
@ -77,6 +77,8 @@ typedef struct _MetaThreadPrivate
|
|||||||
|
|
||||||
MetaThreadType thread_type;
|
MetaThreadType thread_type;
|
||||||
|
|
||||||
|
GThread *main_thread;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
GThread *thread;
|
GThread *thread;
|
||||||
GMutex init_mutex;
|
GMutex init_mutex;
|
||||||
@ -324,6 +326,7 @@ meta_thread_init (MetaThread *thread)
|
|||||||
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||||
|
|
||||||
g_mutex_init (&priv->callbacks_mutex);
|
g_mutex_init (&priv->callbacks_mutex);
|
||||||
|
priv->main_thread = g_thread_self ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -665,7 +668,10 @@ meta_thread_run_impl_task_sync (MetaThread *thread,
|
|||||||
switch (priv->thread_type)
|
switch (priv->thread_type)
|
||||||
{
|
{
|
||||||
case META_THREAD_TYPE_USER:
|
case META_THREAD_TYPE_USER:
|
||||||
|
if (priv->main_thread == g_thread_self ())
|
||||||
return run_impl_task_sync_user (thread, func, user_data, error);
|
return run_impl_task_sync_user (thread, func, user_data, error);
|
||||||
|
else
|
||||||
|
return run_impl_task_sync_kernel (thread, func, user_data, error);
|
||||||
case META_THREAD_TYPE_KERNEL:
|
case META_THREAD_TYPE_KERNEL:
|
||||||
return run_impl_task_sync_kernel (thread, func, user_data, error);
|
return run_impl_task_sync_kernel (thread, func, user_data, error);
|
||||||
}
|
}
|
||||||
|
@ -937,6 +937,108 @@ meta_test_thread_kernel_late_callbacks (void)
|
|||||||
meta_test_thread_late_callbacks_common (META_THREAD_TYPE_KERNEL);
|
meta_test_thread_late_callbacks_common (META_THREAD_TYPE_KERNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GThread *main_thread;
|
||||||
|
GMainLoop *main_thread_loop;
|
||||||
|
MetaThread *thread;
|
||||||
|
GThread *gthread;
|
||||||
|
GMutex init_mutex;
|
||||||
|
|
||||||
|
gboolean done;
|
||||||
|
|
||||||
|
GMainContext *main_context;
|
||||||
|
} RunTaskOffThreadData;
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
run_task_off_thread_in_impl (MetaThreadImpl *thread_impl,
|
||||||
|
gpointer user_data,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
RunTaskOffThreadData *data = user_data;
|
||||||
|
|
||||||
|
g_assert (data->gthread != g_thread_self ());
|
||||||
|
|
||||||
|
g_assert_false (data->done);
|
||||||
|
data->done = TRUE;
|
||||||
|
|
||||||
|
return GINT_TO_POINTER (42);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
run_task_off_thread_thread_func (gpointer user_data)
|
||||||
|
{
|
||||||
|
RunTaskOffThreadData *data = user_data;
|
||||||
|
gpointer result;
|
||||||
|
|
||||||
|
g_mutex_lock (&data->init_mutex);
|
||||||
|
g_mutex_unlock (&data->init_mutex);
|
||||||
|
|
||||||
|
g_assert (data->gthread == g_thread_self ());
|
||||||
|
|
||||||
|
result = meta_thread_run_impl_task_sync (data->thread,
|
||||||
|
run_task_off_thread_in_impl,
|
||||||
|
data,
|
||||||
|
NULL);
|
||||||
|
g_assert_cmpint (GPOINTER_TO_INT (result), ==, 42);
|
||||||
|
g_assert_true (data->done);
|
||||||
|
|
||||||
|
g_idle_add (quit_main_loop, data->main_thread_loop);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_test_thread_run_task_off_thread_common (MetaThreadType thread_type)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_context_get_backend (test_context);
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
RunTaskOffThreadData data = { 0 };
|
||||||
|
|
||||||
|
g_mutex_init (&data.init_mutex);
|
||||||
|
g_mutex_lock (&data.init_mutex);
|
||||||
|
|
||||||
|
data.thread = g_initable_new (META_TYPE_THREAD_TEST,
|
||||||
|
NULL, &error,
|
||||||
|
"backend", backend,
|
||||||
|
"name", "test run task off thread",
|
||||||
|
"thread-type", thread_type,
|
||||||
|
NULL);
|
||||||
|
g_object_add_weak_pointer (G_OBJECT (data.thread), (gpointer *) &data.thread);
|
||||||
|
g_assert_nonnull (data.thread);
|
||||||
|
g_assert_null (error);
|
||||||
|
|
||||||
|
data.main_thread = g_thread_self ();
|
||||||
|
data.main_thread_loop = g_main_loop_new (NULL, FALSE);
|
||||||
|
data.gthread = g_thread_new ("run task off thread test",
|
||||||
|
run_task_off_thread_thread_func,
|
||||||
|
&data);
|
||||||
|
g_assert (data.main_thread != data.gthread);
|
||||||
|
|
||||||
|
g_mutex_unlock (&data.init_mutex);
|
||||||
|
|
||||||
|
g_main_loop_run (data.main_thread_loop);
|
||||||
|
g_main_loop_unref (data.main_thread_loop);
|
||||||
|
|
||||||
|
g_thread_join (data.gthread);
|
||||||
|
g_mutex_clear (&data.init_mutex);
|
||||||
|
|
||||||
|
g_object_unref (data.thread);
|
||||||
|
g_assert_null (data.thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_test_thread_user_run_task_off_thread (void)
|
||||||
|
{
|
||||||
|
meta_test_thread_run_task_off_thread_common (META_THREAD_TYPE_USER);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_test_thread_kernel_run_task_off_thread (void)
|
||||||
|
{
|
||||||
|
meta_test_thread_run_task_off_thread_common (META_THREAD_TYPE_KERNEL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_tests (void)
|
init_tests (void)
|
||||||
{
|
{
|
||||||
@ -948,6 +1050,10 @@ init_tests (void)
|
|||||||
meta_test_thread_user_late_callbacks);
|
meta_test_thread_user_late_callbacks);
|
||||||
g_test_add_func ("/backends/native/thread/kernel/late-callbacks",
|
g_test_add_func ("/backends/native/thread/kernel/late-callbacks",
|
||||||
meta_test_thread_kernel_late_callbacks);
|
meta_test_thread_kernel_late_callbacks);
|
||||||
|
g_test_add_func ("/backends/native/thread/user/run-task-off-thread",
|
||||||
|
meta_test_thread_user_run_task_off_thread);
|
||||||
|
g_test_add_func ("/backends/native/thread/kernel/run-task-off-thread",
|
||||||
|
meta_test_thread_kernel_run_task_off_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
Loading…
Reference in New Issue
Block a user