mutter/src/backends/native/meta-thread.h
Jonas Ådahl 788ad43e17 thread: Allow switching thread type
This will be necessary in order to default to 'kernel' and then switch
to 'user' if the thread instance can no longer be properly multi
threaded.

To avoid having the same thread impl creating and destroying
GMainContext's, this also means always creating a GMainContext for the
thread-impl. When running in user-thread mode, the GMainContext is
wrapped in a wrapper source and dispatched as part of the real main
thread GMainContext, and when in kernel-thread mode, it runs
independently in the dedicated thread.

This has the consequence that the wrapper source will always have the
priority of the highest impl context GSource, but only after it has
dispatched once. Would we need it earlier than that, we either need a
way to introspect existing sources in a GMainContext and their
priorities, or manually track known sources in MetaThreadImpl.

The wrapper source will never be below 0, as that'd mean it could reach
INT_MAX priority if it had no more sources attached to it, meaning it'd
never be dispatched again.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2777>
2023-07-17 21:19:34 +02:00

112 lines
4.0 KiB
C

/*
* Copyright (C) 2018-2021 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_THREAD_H
#define META_THREAD_H
#include <glib-object.h>
#include "backends/meta-backend-types.h"
#include "core/util-private.h"
typedef struct _MetaThreadImpl MetaThreadImpl;
typedef enum _MetaThreadType
{
META_THREAD_TYPE_KERNEL,
META_THREAD_TYPE_USER,
} MetaThreadType;
#define META_TYPE_THREAD (meta_thread_get_type ())
META_EXPORT_TEST
G_DECLARE_DERIVABLE_TYPE (MetaThread, meta_thread,
META, THREAD,
GObject)
struct _MetaThreadClass
{
GObjectClass parent_class;
};
typedef void (* MetaThreadCallback) (MetaThread *thread,
gpointer user_data);
typedef gpointer (* MetaThreadTaskFunc) (MetaThreadImpl *thread_impl,
gpointer user_data,
GError **error);
typedef void (* MetaThreadTaskFeedbackFunc) (gpointer retval,
const GError *error,
gpointer user_data);
META_EXPORT_TEST
void meta_thread_reset_thread_type (MetaThread *thread,
MetaThreadType thread_type);
META_EXPORT_TEST
void meta_thread_register_callback_context (MetaThread *thread,
GMainContext *main_context);
META_EXPORT_TEST
void meta_thread_unregister_callback_context (MetaThread *thread,
GMainContext *main_context);
META_EXPORT_TEST
void meta_thread_queue_callback (MetaThread *thread,
GMainContext *main_context,
MetaThreadCallback callback,
gpointer user_data,
GDestroyNotify user_data_destroy);
META_EXPORT_TEST
void meta_thread_flush_callbacks (MetaThread *thread);
META_EXPORT_TEST
gpointer meta_thread_run_impl_task_sync (MetaThread *thread,
MetaThreadTaskFunc func,
gpointer user_data,
GError **error);
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);
META_EXPORT_TEST
MetaBackend * meta_thread_get_backend (MetaThread *thread);
META_EXPORT_TEST
const char * meta_thread_get_name (MetaThread *thread);
META_EXPORT_TEST
gboolean meta_thread_is_in_impl_task (MetaThread *thread);
gboolean meta_thread_is_waiting_for_impl_task (MetaThread *thread);
#define meta_assert_in_thread_impl(thread) \
g_assert (meta_thread_is_in_impl_task (thread))
#define meta_assert_not_in_thread_impl(thread) \
g_assert (!meta_thread_is_in_impl_task (thread))
#define meta_assert_is_waiting_for_thread_impl_task(thread) \
g_assert (meta_thread_is_waiting_for_impl_task (thread))
#endif /* META_THREAD_H */