thread: Move context and task management to impl side
It's the impl side that wants to add impl side idle sources, or fd sources, etc, so make it part of MetaThreadImpl. This changes things to be GAsyncQueue based. While things are still technically single threaded, the GAsyncQueue type is used as later we'll introduce queuing tasks asynchronously, then eventually queuing across thread barriers. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
This commit is contained in:
parent
229904cb4b
commit
fda883e859
@ -31,6 +31,7 @@
|
||||
#include "backends/native/meta-kms-private.h"
|
||||
#include "backends/native/meta-kms-update-private.h"
|
||||
#include "backends/native/meta-kms-utils.h"
|
||||
#include "backends/native/meta-thread-impl.h"
|
||||
|
||||
typedef gboolean (* MetaKmsSimpleProcessFunc) (MetaKmsImplDevice *impl_device,
|
||||
MetaKmsUpdate *update,
|
||||
@ -757,12 +758,12 @@ schedule_retry_page_flip (MetaKmsImplDeviceSimple *impl_device_simple,
|
||||
{
|
||||
MetaKmsImplDevice *impl_device =
|
||||
META_KMS_IMPL_DEVICE (impl_device_simple);
|
||||
MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device);
|
||||
MetaKms *kms = meta_kms_device_get_kms (device);
|
||||
MetaKmsImpl *impl = meta_kms_impl_device_get_impl (impl_device);
|
||||
MetaThreadImpl *thread_impl = META_THREAD_IMPL (impl);
|
||||
GSource *source;
|
||||
|
||||
source = meta_thread_add_source_in_impl (META_THREAD (kms), retry_page_flips,
|
||||
impl_device_simple, NULL);
|
||||
source = meta_thread_impl_add_source (thread_impl, retry_page_flips,
|
||||
impl_device_simple, NULL);
|
||||
g_source_set_ready_time (source, retry_time_us);
|
||||
|
||||
impl_device_simple->retry_page_flips_source = source;
|
||||
@ -831,8 +832,6 @@ mode_set_fallback (MetaKmsImplDeviceSimple *impl_device_simple,
|
||||
GError **error)
|
||||
{
|
||||
MetaKmsImplDevice *impl_device = META_KMS_IMPL_DEVICE (impl_device_simple);
|
||||
MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device);
|
||||
MetaKms *kms = meta_kms_device_get_kms (device);
|
||||
MetaKmsCrtc *crtc = meta_kms_page_flip_data_get_crtc (page_flip_data);
|
||||
CachedModeSet *cached_mode_set;
|
||||
g_autofree uint32_t *connectors = NULL;
|
||||
@ -882,12 +881,14 @@ mode_set_fallback (MetaKmsImplDeviceSimple *impl_device_simple,
|
||||
|
||||
if (!impl_device_simple->mode_set_fallback_feedback_source)
|
||||
{
|
||||
MetaKmsImpl *impl = meta_kms_impl_device_get_impl (impl_device);
|
||||
MetaThreadImpl *thread_impl = META_THREAD_IMPL (impl);
|
||||
GSource *source;
|
||||
|
||||
source = meta_thread_add_source_in_impl (META_THREAD (kms),
|
||||
mode_set_fallback_feedback_idle,
|
||||
impl_device_simple,
|
||||
NULL);
|
||||
source = meta_thread_impl_add_source (thread_impl,
|
||||
mode_set_fallback_feedback_idle,
|
||||
impl_device_simple,
|
||||
NULL);
|
||||
impl_device_simple->mode_set_fallback_feedback_source = source;
|
||||
}
|
||||
|
||||
@ -941,16 +942,16 @@ dispatch_page_flip (MetaKmsImplDevice *impl_device,
|
||||
|
||||
if (!plane_assignment && !custom_page_flip)
|
||||
{
|
||||
MetaKmsDevice *device = meta_kms_impl_device_get_device (impl_device);
|
||||
MetaKms *kms = meta_kms_device_get_kms (device);
|
||||
MetaKmsImpl *impl = meta_kms_impl_device_get_impl (impl_device);
|
||||
MetaThreadImpl *thread_impl = META_THREAD_IMPL (impl);
|
||||
GSource *source;
|
||||
|
||||
meta_kms_page_flip_data_make_symbolic (page_flip_data);
|
||||
|
||||
source = meta_thread_add_source_in_impl (META_THREAD (kms),
|
||||
symbolic_page_flip_idle,
|
||||
page_flip_data,
|
||||
NULL);
|
||||
source = meta_thread_impl_add_source (thread_impl,
|
||||
symbolic_page_flip_idle,
|
||||
page_flip_data,
|
||||
NULL);
|
||||
|
||||
g_source_set_ready_time (source, 0);
|
||||
g_source_unref (source);
|
||||
|
@ -89,6 +89,15 @@ G_DEFINE_TYPE_WITH_CODE (MetaKmsImplDevice, meta_kms_impl_device,
|
||||
|
||||
G_DEFINE_QUARK (-meta-kms-error-quark, meta_kms_error)
|
||||
|
||||
MetaKmsImpl *
|
||||
meta_kms_impl_device_get_impl (MetaKmsImplDevice *impl_device)
|
||||
{
|
||||
MetaKmsImplDevicePrivate *priv =
|
||||
meta_kms_impl_device_get_instance_private (impl_device);
|
||||
|
||||
return priv->impl;
|
||||
}
|
||||
|
||||
MetaKmsDevice *
|
||||
meta_kms_impl_device_get_device (MetaKmsImplDevice *impl_device)
|
||||
{
|
||||
@ -856,13 +865,11 @@ ensure_device_file (MetaKmsImplDevice *impl_device,
|
||||
|
||||
if (!(priv->flags & META_KMS_DEVICE_FLAG_NO_MODE_SETTING))
|
||||
{
|
||||
MetaKms *kms = meta_kms_impl_get_kms (priv->impl);
|
||||
|
||||
priv->fd_source =
|
||||
meta_thread_register_fd_in_impl (META_THREAD (kms),
|
||||
meta_device_file_get_fd (device_file),
|
||||
kms_event_dispatch_in_impl,
|
||||
impl_device);
|
||||
meta_thread_impl_register_fd (META_THREAD_IMPL (priv->impl),
|
||||
meta_device_file_get_fd (device_file),
|
||||
kms_event_dispatch_in_impl,
|
||||
impl_device);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -116,6 +116,8 @@ enum
|
||||
#define META_KMS_ERROR meta_kms_error_quark ()
|
||||
GQuark meta_kms_error_quark (void);
|
||||
|
||||
MetaKmsImpl * meta_kms_impl_device_get_impl (MetaKmsImplDevice *impl_device);
|
||||
|
||||
MetaKmsDevice * meta_kms_impl_device_get_device (MetaKmsImplDevice *impl_device);
|
||||
|
||||
GList * meta_kms_impl_device_copy_connectors (MetaKmsImplDevice *impl_device);
|
||||
|
@ -30,6 +30,7 @@ enum
|
||||
PROP_0,
|
||||
|
||||
PROP_THREAD,
|
||||
PROP_MAIN_CONTEXT,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
@ -39,9 +40,21 @@ static GParamSpec *obj_props[N_PROPS];
|
||||
typedef struct _MetaThreadImplPrivate
|
||||
{
|
||||
MetaThread *thread;
|
||||
|
||||
gboolean in_impl_task;
|
||||
|
||||
GMainContext *thread_context;
|
||||
GAsyncQueue *task_queue;
|
||||
} MetaThreadImplPrivate;
|
||||
|
||||
struct _MetaThreadTask
|
||||
{
|
||||
MetaThreadTaskFunc func;
|
||||
gpointer user_data;
|
||||
MetaThreadTaskFeedbackFunc feedback_func;
|
||||
gpointer feedback_user_data;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaThreadImpl, meta_thread_impl, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
@ -59,6 +72,9 @@ meta_thread_impl_get_property (GObject *object,
|
||||
case PROP_THREAD:
|
||||
g_value_set_object (value, priv->thread);
|
||||
break;
|
||||
case PROP_MAIN_CONTEXT:
|
||||
g_value_set_boxed (value, priv->thread_context);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -80,6 +96,9 @@ meta_thread_impl_set_property (GObject *object,
|
||||
case PROP_THREAD:
|
||||
priv->thread = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_MAIN_CONTEXT:
|
||||
priv->thread_context = g_value_dup_boxed (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -93,9 +112,22 @@ meta_thread_impl_constructed (GObject *object)
|
||||
MetaThreadImplPrivate *priv =
|
||||
meta_thread_impl_get_instance_private (thread_impl);
|
||||
|
||||
G_OBJECT_CLASS (meta_thread_impl_parent_class)->constructed (object);
|
||||
priv->task_queue = g_async_queue_new ();
|
||||
|
||||
priv->thread_context = g_main_context_get_thread_default ();
|
||||
G_OBJECT_CLASS (meta_thread_impl_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_thread_impl_finalize (GObject *object)
|
||||
{
|
||||
MetaThreadImpl *thread_impl = META_THREAD_IMPL (object);
|
||||
MetaThreadImplPrivate *priv =
|
||||
meta_thread_impl_get_instance_private (thread_impl);
|
||||
|
||||
g_clear_pointer (&priv->task_queue, g_async_queue_unref);
|
||||
g_clear_pointer (&priv->thread_context, g_main_context_unref);
|
||||
|
||||
G_OBJECT_CLASS (meta_thread_impl_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -106,6 +138,7 @@ meta_thread_impl_class_init (MetaThreadImplClass *klass)
|
||||
object_class->get_property = meta_thread_impl_get_property;
|
||||
object_class->set_property = meta_thread_impl_set_property;
|
||||
object_class->constructed = meta_thread_impl_constructed;
|
||||
object_class->finalize = meta_thread_impl_finalize;
|
||||
|
||||
obj_props[PROP_THREAD] =
|
||||
g_param_spec_object ("thread",
|
||||
@ -115,6 +148,14 @@ meta_thread_impl_class_init (MetaThreadImplClass *klass)
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
obj_props[PROP_MAIN_CONTEXT] =
|
||||
g_param_spec_boxed ("main-context",
|
||||
"main-context",
|
||||
"GMainContext",
|
||||
G_TYPE_MAIN_CONTEXT,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_properties (object_class, N_PROPS, obj_props);
|
||||
}
|
||||
|
||||
@ -140,3 +181,219 @@ meta_thread_impl_get_main_context (MetaThreadImpl *thread_impl)
|
||||
|
||||
return priv->thread_context;
|
||||
}
|
||||
|
||||
MetaThreadTask *
|
||||
meta_thread_task_new (MetaThreadTaskFunc func,
|
||||
gpointer user_data,
|
||||
MetaThreadTaskFeedbackFunc feedback_func,
|
||||
gpointer feedback_user_data)
|
||||
{
|
||||
MetaThreadTask *task;
|
||||
|
||||
task = g_new0 (MetaThreadTask, 1);
|
||||
*task = (MetaThreadTask) {
|
||||
.func = func,
|
||||
.user_data = user_data,
|
||||
.feedback_func = feedback_func,
|
||||
.feedback_user_data = feedback_user_data,
|
||||
};
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
void
|
||||
meta_thread_task_free (MetaThreadTask *task)
|
||||
{
|
||||
g_free (task);
|
||||
}
|
||||
|
||||
typedef struct _MetaThreadImplIdleSource
|
||||
{
|
||||
GSource source;
|
||||
MetaThreadImpl *thread_impl;
|
||||
} MetaThreadImplIdleSource;
|
||||
|
||||
static gboolean
|
||||
impl_idle_source_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaThreadImplIdleSource *impl_idle_source =
|
||||
(MetaThreadImplIdleSource *) source;
|
||||
MetaThreadImpl *thread_impl = impl_idle_source->thread_impl;
|
||||
MetaThreadImplPrivate *priv =
|
||||
meta_thread_impl_get_instance_private (thread_impl);
|
||||
gboolean ret;
|
||||
|
||||
priv->in_impl_task = TRUE;
|
||||
ret = callback (user_data);
|
||||
priv->in_impl_task = FALSE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GSourceFuncs impl_idle_source_funcs = {
|
||||
.dispatch = impl_idle_source_dispatch,
|
||||
};
|
||||
|
||||
GSource *
|
||||
meta_thread_impl_add_source (MetaThreadImpl *thread_impl,
|
||||
GSourceFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_data_destroy)
|
||||
{
|
||||
MetaThreadImplPrivate *priv =
|
||||
meta_thread_impl_get_instance_private (thread_impl);
|
||||
GSource *source;
|
||||
MetaThreadImplIdleSource *impl_idle_source;
|
||||
|
||||
meta_assert_in_thread_impl (priv->thread);
|
||||
|
||||
source = g_source_new (&impl_idle_source_funcs,
|
||||
sizeof (MetaThreadImplIdleSource));
|
||||
g_source_set_name (source, "[mutter] MetaThreadImpl idle source");
|
||||
impl_idle_source = (MetaThreadImplIdleSource *) source;
|
||||
impl_idle_source->thread_impl = thread_impl;
|
||||
|
||||
g_source_set_callback (source, func, user_data, user_data_destroy);
|
||||
g_source_set_ready_time (source, 0);
|
||||
g_source_attach (source, priv->thread_context);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
typedef struct _MetaThreadImplFdSource
|
||||
{
|
||||
GSource source;
|
||||
|
||||
gpointer fd_tag;
|
||||
MetaThreadImpl *thread_impl;
|
||||
|
||||
MetaThreadTaskFunc dispatch;
|
||||
gpointer user_data;
|
||||
} MetaThreadImplFdSource;
|
||||
|
||||
static gboolean
|
||||
meta_thread_impl_fd_source_check (GSource *source)
|
||||
{
|
||||
MetaThreadImplFdSource *impl_fd_source = (MetaThreadImplFdSource *) source;
|
||||
|
||||
return g_source_query_unix_fd (source, impl_fd_source->fd_tag) & G_IO_IN;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
dispatch_task_func (MetaThreadImpl *thread_impl,
|
||||
MetaThreadTaskFunc dispatch,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
MetaThreadImplPrivate *priv =
|
||||
meta_thread_impl_get_instance_private (thread_impl);
|
||||
gpointer retval = NULL;
|
||||
|
||||
priv->in_impl_task = TRUE;
|
||||
retval = dispatch (thread_impl, user_data, error);
|
||||
priv->in_impl_task = FALSE;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_thread_impl_fd_source_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaThreadImplFdSource *impl_fd_source = (MetaThreadImplFdSource *) source;
|
||||
MetaThreadImpl *thread_impl = impl_fd_source->thread_impl;
|
||||
gpointer retval;
|
||||
GError *error = NULL;
|
||||
|
||||
retval = dispatch_task_func (thread_impl,
|
||||
impl_fd_source->dispatch,
|
||||
impl_fd_source->user_data,
|
||||
&error);
|
||||
|
||||
if (!GPOINTER_TO_INT (retval))
|
||||
{
|
||||
g_warning ("Failed to dispatch fd source: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static GSourceFuncs impl_fd_source_funcs = {
|
||||
NULL,
|
||||
meta_thread_impl_fd_source_check,
|
||||
meta_thread_impl_fd_source_dispatch
|
||||
};
|
||||
|
||||
GSource *
|
||||
meta_thread_impl_register_fd (MetaThreadImpl *thread_impl,
|
||||
int fd,
|
||||
MetaThreadTaskFunc dispatch,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaThreadImplPrivate *priv =
|
||||
meta_thread_impl_get_instance_private (thread_impl);
|
||||
GSource *source;
|
||||
MetaThreadImplFdSource *impl_fd_source;
|
||||
|
||||
meta_assert_in_thread_impl (priv->thread);
|
||||
|
||||
source = g_source_new (&impl_fd_source_funcs,
|
||||
sizeof (MetaThreadImplFdSource));
|
||||
g_source_set_name (source, "[mutter] MetaThreadImpl fd source");
|
||||
impl_fd_source = (MetaThreadImplFdSource *) source;
|
||||
impl_fd_source->dispatch = dispatch;
|
||||
impl_fd_source->user_data = user_data;
|
||||
impl_fd_source->thread_impl = thread_impl;
|
||||
impl_fd_source->fd_tag = g_source_add_unix_fd (source, fd,
|
||||
G_IO_IN | G_IO_ERR);
|
||||
|
||||
g_source_attach (source, priv->thread_context);
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_thread_impl_is_in_impl (MetaThreadImpl *thread_impl)
|
||||
{
|
||||
MetaThreadImplPrivate *priv =
|
||||
meta_thread_impl_get_instance_private (thread_impl);
|
||||
|
||||
return priv->in_impl_task;
|
||||
}
|
||||
|
||||
void
|
||||
meta_thread_impl_dispatch (MetaThreadImpl *thread_impl)
|
||||
{
|
||||
MetaThreadImplPrivate *priv =
|
||||
meta_thread_impl_get_instance_private (thread_impl);
|
||||
MetaThreadTask *task;
|
||||
gpointer retval;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
task = g_async_queue_pop (priv->task_queue);
|
||||
|
||||
priv->in_impl_task = TRUE;
|
||||
retval = task->func (thread_impl, task->user_data, &error);
|
||||
|
||||
if (task->feedback_func)
|
||||
task->feedback_func (retval, error, task->feedback_user_data);
|
||||
|
||||
meta_thread_task_free (task);
|
||||
|
||||
priv->in_impl_task = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_thread_impl_queue_task (MetaThreadImpl *thread_impl,
|
||||
MetaThreadTask *task)
|
||||
{
|
||||
MetaThreadImplPrivate *priv =
|
||||
meta_thread_impl_get_instance_private (thread_impl);
|
||||
|
||||
g_async_queue_push (priv->task_queue, task);
|
||||
g_main_context_wakeup (priv->thread_context);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "backends/native/meta-thread.h"
|
||||
#include "core/util-private.h"
|
||||
|
||||
typedef struct _MetaThread MetaThread;
|
||||
@ -36,9 +37,41 @@ struct _MetaThreadImplClass
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
typedef struct _MetaThreadTask MetaThreadTask;
|
||||
|
||||
typedef void (* MetaThreadTaskFeedbackFunc) (gpointer retval,
|
||||
const GError *error,
|
||||
gpointer user_data);
|
||||
|
||||
META_EXPORT_TEST
|
||||
MetaThread * meta_thread_impl_get_thread (MetaThreadImpl *thread_impl);
|
||||
|
||||
GMainContext * meta_thread_impl_get_main_context (MetaThreadImpl *thread_impl);
|
||||
|
||||
META_EXPORT_TEST
|
||||
GSource * meta_thread_impl_add_source (MetaThreadImpl *thread_impl,
|
||||
GSourceFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_data_destroy);
|
||||
|
||||
META_EXPORT_TEST
|
||||
GSource * meta_thread_impl_register_fd (MetaThreadImpl *thread_impl,
|
||||
int fd,
|
||||
MetaThreadTaskFunc dispatch,
|
||||
gpointer user_data);
|
||||
|
||||
void meta_thread_impl_queue_task (MetaThreadImpl *thread_impl,
|
||||
MetaThreadTask *task);
|
||||
|
||||
void meta_thread_impl_dispatch (MetaThreadImpl *thread_impl);
|
||||
|
||||
gboolean meta_thread_impl_is_in_impl (MetaThreadImpl *thread_impl);
|
||||
|
||||
MetaThreadTask * meta_thread_task_new (MetaThreadTaskFunc func,
|
||||
gpointer user_data,
|
||||
MetaThreadTaskFeedbackFunc feedback_func,
|
||||
gpointer feedback_user_data);
|
||||
|
||||
void meta_thread_task_free (MetaThreadTask *task);
|
||||
|
||||
#endif /* META_THREAD_IMPL_H */
|
||||
|
@ -43,23 +43,6 @@ typedef struct _MetaThreadCallbackData
|
||||
GDestroyNotify user_data_destroy;
|
||||
} MetaThreadCallbackData;
|
||||
|
||||
typedef struct _MetaThreadSimpleImplSource
|
||||
{
|
||||
GSource source;
|
||||
MetaThread *thread;
|
||||
} MetaThreadSimpleImplSource;
|
||||
|
||||
typedef struct _MetaThreadFdImplSource
|
||||
{
|
||||
GSource source;
|
||||
|
||||
gpointer fd_tag;
|
||||
MetaThread *thread;
|
||||
|
||||
MetaThreadTaskFunc dispatch;
|
||||
gpointer user_data;
|
||||
} MetaThreadFdImplSource;
|
||||
|
||||
typedef struct _MetaThreadPrivate
|
||||
{
|
||||
MetaBackend *backend;
|
||||
@ -67,7 +50,6 @@ typedef struct _MetaThreadPrivate
|
||||
GMainContext *main_context;
|
||||
|
||||
MetaThreadImpl *impl;
|
||||
gboolean in_impl_task;
|
||||
gboolean waiting_for_impl_task;
|
||||
|
||||
GList *pending_callbacks;
|
||||
@ -147,12 +129,16 @@ meta_thread_initable_init (GInitable *initable,
|
||||
MetaThreadClassPrivate *class_priv =
|
||||
G_TYPE_CLASS_GET_PRIVATE (thread_class, META_TYPE_THREAD,
|
||||
MetaThreadClassPrivate);
|
||||
g_autoptr (GMainContext) thread_context = NULL;
|
||||
|
||||
priv->main_context = g_main_context_get_thread_default ();
|
||||
priv->main_context = g_main_context_default ();
|
||||
|
||||
thread_context = g_main_context_ref (priv->main_context);
|
||||
|
||||
g_assert (g_type_is_a (class_priv->impl_type, META_TYPE_THREAD_IMPL));
|
||||
priv->impl = g_object_new (class_priv->impl_type,
|
||||
"thread", thread,
|
||||
"main-context", thread_context,
|
||||
NULL);
|
||||
|
||||
return TRUE;
|
||||
@ -282,6 +268,25 @@ meta_thread_queue_callback (MetaThread *thread,
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _MetaSyncTaskData
|
||||
{
|
||||
gboolean done;
|
||||
GError *error;
|
||||
gpointer retval;
|
||||
} MetaSyncTaskData;
|
||||
|
||||
static void
|
||||
sync_task_done_in_impl (gpointer retval,
|
||||
const GError *error,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaSyncTaskData *data = user_data;
|
||||
|
||||
data->done = TRUE;
|
||||
data->retval = retval;
|
||||
data->error = error ? g_error_copy (error) : NULL;
|
||||
}
|
||||
|
||||
gpointer
|
||||
meta_thread_run_impl_task_sync (MetaThread *thread,
|
||||
MetaThreadTaskFunc func,
|
||||
@ -289,129 +294,24 @@ meta_thread_run_impl_task_sync (MetaThread *thread,
|
||||
GError **error)
|
||||
{
|
||||
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||
gpointer ret;
|
||||
MetaThreadTask *task;
|
||||
MetaSyncTaskData data = { 0 };
|
||||
|
||||
task = meta_thread_task_new (func, user_data,
|
||||
sync_task_done_in_impl, &data);
|
||||
meta_thread_impl_queue_task (priv->impl, task);
|
||||
|
||||
priv->in_impl_task = TRUE;
|
||||
priv->waiting_for_impl_task = TRUE;
|
||||
ret = func (priv->impl, user_data, error);
|
||||
while (!data.done)
|
||||
meta_thread_impl_dispatch (priv->impl);
|
||||
priv->waiting_for_impl_task = FALSE;
|
||||
priv->in_impl_task = FALSE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
if (error)
|
||||
*error = data.error;
|
||||
else
|
||||
g_clear_error (&data.error);
|
||||
|
||||
static gboolean
|
||||
simple_impl_source_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaThreadSimpleImplSource *simple_impl_source =
|
||||
(MetaThreadSimpleImplSource *) source;
|
||||
MetaThread *thread = simple_impl_source->thread;
|
||||
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||
gboolean ret;
|
||||
|
||||
priv->in_impl_task = TRUE;
|
||||
ret = callback (user_data);
|
||||
priv->in_impl_task = FALSE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GSourceFuncs simple_impl_source_funcs = {
|
||||
.dispatch = simple_impl_source_dispatch,
|
||||
};
|
||||
|
||||
GSource *
|
||||
meta_thread_add_source_in_impl (MetaThread *thread,
|
||||
GSourceFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_data_destroy)
|
||||
{
|
||||
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||
GSource *source;
|
||||
MetaThreadSimpleImplSource *simple_impl_source;
|
||||
|
||||
meta_assert_in_thread_impl (thread);
|
||||
|
||||
source = g_source_new (&simple_impl_source_funcs,
|
||||
sizeof (MetaThreadSimpleImplSource));
|
||||
g_source_set_name (source, "[mutter] MetaThread simple impl");
|
||||
simple_impl_source = (MetaThreadSimpleImplSource *) source;
|
||||
simple_impl_source->thread = thread;
|
||||
|
||||
g_source_set_callback (source, func, user_data, user_data_destroy);
|
||||
g_source_set_ready_time (source, 0);
|
||||
g_source_attach (source, meta_thread_impl_get_main_context (priv->impl));
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_thread_fd_impl_source_check (GSource *source)
|
||||
{
|
||||
MetaThreadFdImplSource *fd_impl_source = (MetaThreadFdImplSource *) source;
|
||||
|
||||
return g_source_query_unix_fd (source, fd_impl_source->fd_tag) & G_IO_IN;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_thread_fd_impl_source_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaThreadFdImplSource *fd_impl_source = (MetaThreadFdImplSource *) source;
|
||||
MetaThread *thread = fd_impl_source->thread;
|
||||
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||
gpointer ret;
|
||||
GError *error = NULL;
|
||||
|
||||
priv->in_impl_task = TRUE;
|
||||
ret = fd_impl_source->dispatch (priv->impl,
|
||||
fd_impl_source->user_data,
|
||||
&error);
|
||||
priv->in_impl_task = FALSE;
|
||||
|
||||
if (!GPOINTER_TO_INT (ret))
|
||||
{
|
||||
g_warning ("Failed to dispatch fd source: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static GSourceFuncs fd_impl_source_funcs = {
|
||||
NULL,
|
||||
meta_thread_fd_impl_source_check,
|
||||
meta_thread_fd_impl_source_dispatch
|
||||
};
|
||||
|
||||
GSource *
|
||||
meta_thread_register_fd_in_impl (MetaThread *thread,
|
||||
int fd,
|
||||
MetaThreadTaskFunc dispatch,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||
GSource *source;
|
||||
MetaThreadFdImplSource *fd_impl_source;
|
||||
|
||||
meta_assert_in_thread_impl (thread);
|
||||
|
||||
source = g_source_new (&fd_impl_source_funcs,
|
||||
sizeof (MetaThreadFdImplSource));
|
||||
g_source_set_name (source, "[mutter] MetaThread fd impl");
|
||||
fd_impl_source = (MetaThreadFdImplSource *) source;
|
||||
fd_impl_source->dispatch = dispatch;
|
||||
fd_impl_source->user_data = user_data;
|
||||
fd_impl_source->thread = thread;
|
||||
fd_impl_source->fd_tag = g_source_add_unix_fd (source, fd,
|
||||
G_IO_IN | G_IO_ERR);
|
||||
|
||||
g_source_attach (source, meta_thread_impl_get_main_context (priv->impl));
|
||||
|
||||
return source;
|
||||
return data.retval;
|
||||
}
|
||||
|
||||
MetaBackend *
|
||||
@ -427,7 +327,7 @@ meta_thread_is_in_impl_task (MetaThread *thread)
|
||||
{
|
||||
MetaThreadPrivate *priv = meta_thread_get_instance_private (thread);
|
||||
|
||||
return priv->in_impl_task;
|
||||
return meta_thread_impl_is_in_impl (priv->impl);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -60,18 +60,6 @@ gpointer meta_thread_run_impl_task_sync (MetaThread *thread,
|
||||
gpointer user_data,
|
||||
GError **error);
|
||||
|
||||
META_EXPORT_TEST
|
||||
GSource * meta_thread_add_source_in_impl (MetaThread *thread,
|
||||
GSourceFunc func,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_data_destroy);
|
||||
|
||||
META_EXPORT_TEST
|
||||
GSource * meta_thread_register_fd_in_impl (MetaThread *thread,
|
||||
int fd,
|
||||
MetaThreadTaskFunc dispatch,
|
||||
gpointer user_data);
|
||||
|
||||
META_EXPORT_TEST
|
||||
MetaBackend * meta_thread_get_backend (MetaThread *thread);
|
||||
|
||||
|
@ -125,11 +125,10 @@ register_fd_func (MetaThreadImpl *thread_impl,
|
||||
{
|
||||
PipeData *pipe_data = user_data;
|
||||
|
||||
pipe_data->source =
|
||||
meta_thread_register_fd_in_impl (meta_thread_impl_get_thread (thread_impl),
|
||||
pipe_data->fd,
|
||||
dispatch_pipe,
|
||||
pipe_data);
|
||||
pipe_data->source = meta_thread_impl_register_fd (thread_impl,
|
||||
pipe_data->fd,
|
||||
dispatch_pipe,
|
||||
pipe_data);
|
||||
|
||||
return GINT_TO_POINTER (TRUE);
|
||||
}
|
||||
@ -185,11 +184,10 @@ add_idle_func (MetaThreadImpl *thread_impl,
|
||||
|
||||
meta_assert_in_thread_impl (meta_thread_impl_get_thread (thread_impl));
|
||||
|
||||
source =
|
||||
meta_thread_add_source_in_impl (meta_thread_impl_get_thread (thread_impl),
|
||||
idle_cb,
|
||||
idle_data,
|
||||
idle_data_destroy);
|
||||
source = meta_thread_impl_add_source (thread_impl,
|
||||
idle_cb,
|
||||
idle_data,
|
||||
idle_data_destroy);
|
||||
g_source_unref (source);
|
||||
|
||||
return GINT_TO_POINTER (TRUE);
|
||||
|
Loading…
Reference in New Issue
Block a user