From 2bbd2e55637430f011a35161e397f88b9dffd3c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Sun, 10 Mar 2019 13:36:34 +0100 Subject: [PATCH] kms: Add API to post callbacks out of the impl context While the current impl context is in the same thread as the main context, the separation still exists, and to post callbacks from the impl context, it must pass MetaKms to make sure the callback is invoked in the right context. https://gitlab.gnome.org/GNOME/mutter/issues/548 https://gitlab.gnome.org/GNOME/mutter/merge_requests/525 --- src/backends/native/meta-kms-private.h | 8 ++++ src/backends/native/meta-kms.c | 66 ++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/src/backends/native/meta-kms-private.h b/src/backends/native/meta-kms-private.h index da59d7431..8c0ce9425 100644 --- a/src/backends/native/meta-kms-private.h +++ b/src/backends/native/meta-kms-private.h @@ -24,10 +24,18 @@ #include "backends/native/meta-kms-types.h" +typedef void (* MetaKmsCallback) (MetaKms *kms, + gpointer user_data); + typedef gboolean (* MetaKmsImplTaskFunc) (MetaKmsImpl *impl, gpointer user_data, GError **error); +void meta_kms_queue_callback (MetaKms *kms, + MetaKmsCallback callback, + gpointer user_data, + GDestroyNotify user_data_destroy); + gboolean meta_kms_run_impl_task_sync (MetaKms *kms, MetaKmsImplTaskFunc func, gpointer user_data, diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c index 4fd9c5ee4..408b9f5a2 100644 --- a/src/backends/native/meta-kms.c +++ b/src/backends/native/meta-kms.c @@ -27,6 +27,13 @@ #include "backends/native/meta-kms-impl-simple.h" #include "backends/native/meta-udev.h" +typedef struct _MetaKmsCallbackData +{ + MetaKmsCallback callback; + gpointer user_data; + GDestroyNotify user_data_destroy; +} MetaKmsCallbackData; + struct _MetaKms { GObject parent; @@ -39,10 +46,62 @@ struct _MetaKms gboolean in_impl_task; GList *devices; + + GList *pending_callbacks; + guint callback_source_id; }; G_DEFINE_TYPE (MetaKms, meta_kms, G_TYPE_OBJECT) +static void +meta_kms_callback_data_free (MetaKmsCallbackData *callback_data) +{ + if (callback_data->user_data_destroy) + callback_data->user_data_destroy (callback_data->user_data); + g_slice_free (MetaKmsCallbackData, callback_data); +} + +static gboolean +callback_idle (gpointer user_data) +{ + MetaKms *kms = user_data; + GList *l; + + for (l = kms->pending_callbacks; l; l = l->next) + { + MetaKmsCallbackData *callback_data = l->data; + + callback_data->callback (kms, callback_data->user_data); + meta_kms_callback_data_free (callback_data); + } + + g_list_free (kms->pending_callbacks); + kms->pending_callbacks = NULL; + + kms->callback_source_id = 0; + return G_SOURCE_REMOVE; +} + +void +meta_kms_queue_callback (MetaKms *kms, + MetaKmsCallback callback, + gpointer user_data, + GDestroyNotify user_data_destroy) +{ + MetaKmsCallbackData *callback_data; + + callback_data = g_slice_new0 (MetaKmsCallbackData); + *callback_data = (MetaKmsCallbackData) { + .callback = callback, + .user_data = user_data, + .user_data_destroy = user_data_destroy, + }; + kms->pending_callbacks = g_list_append (kms->pending_callbacks, + callback_data); + if (!kms->callback_source_id) + kms->callback_source_id = g_idle_add (callback_idle, kms); +} + gboolean meta_kms_run_impl_task_sync (MetaKms *kms, MetaKmsImplTaskFunc func, @@ -155,6 +214,13 @@ meta_kms_finalize (GObject *object) MetaKms *kms = META_KMS (object); MetaBackendNative *backend_native = META_BACKEND_NATIVE (kms->backend); MetaUdev *udev = meta_backend_native_get_udev (backend_native); + GList *l; + + for (l = kms->pending_callbacks; l; l = l->next) + meta_kms_callback_data_free (l->data); + g_list_free (kms->pending_callbacks); + + g_clear_handle_id (&kms->callback_source_id, g_source_remove); g_list_free_full (kms->devices, g_object_unref);