diff options
author | Sebastian Dröge <slomo@coaxion.net> | 2019-10-24 11:58:34 +0000 |
---|---|---|
committer | Sebastian Dröge <slomo@coaxion.net> | 2019-10-24 11:58:34 +0000 |
commit | 2e9b2761d673c0efd477d83a0f0796966abf58f1 (patch) | |
tree | 7460a5bf224dfc6dd9f0ed2933af29189a8d445a | |
parent | 05be19b9f71fb6a8ae89b06cf672b6a26cd0965f (diff) | |
parent | 21f8f8982020dfd65d8d20a5fd0ace67a6dee856 (diff) | |
download | glib-2e9b2761d673c0efd477d83a0f0796966abf58f1.tar.gz |
Merge branch 'main-context-pusher' into 'master'
gmain: Add GMainContextPusher convenience API
See merge request GNOME/glib!983
-rw-r--r-- | docs/reference/glib/glib-sections.txt | 5 | ||||
-rw-r--r-- | glib/glib-autocleanups.h | 7 | ||||
-rw-r--r-- | glib/gmain.h | 83 | ||||
-rw-r--r-- | glib/tests/autoptr.c | 25 |
4 files changed, 120 insertions, 0 deletions
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index eea025c92..e9dfa73e9 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -782,6 +782,11 @@ g_main_context_invoke g_main_context_invoke_full <SUBSECTION> +GMainContextPusher +g_main_context_pusher_new +g_main_context_pusher_free + +<SUBSECTION> g_main_context_get_thread_default g_main_context_ref_thread_default g_main_context_push_thread_default diff --git a/glib/glib-autocleanups.h b/glib/glib-autocleanups.h index efa4a99ab..b71101f2d 100644 --- a/glib/glib-autocleanups.h +++ b/glib/glib-autocleanups.h @@ -35,6 +35,10 @@ g_autoptr_cleanup_gstring_free (GString *string) g_string_free (string, TRUE); } +/* Ignore deprecations in case we refer to a type which was added in a more + * recent GLib version than the user’s #GLIB_VERSION_MAX_ALLOWED definition. */ +G_GNUC_BEGIN_IGNORE_DEPRECATIONS + /* If adding a cleanup here, please also add a test case to * glib/tests/autoptr.c */ @@ -54,6 +58,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GArray, g_array_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GPtrArray, g_ptr_array_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GByteArray, g_byte_array_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GMainContext, g_main_context_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GMainContextPusher, g_main_context_pusher_free) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GMainLoop, g_main_loop_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GSource, g_source_unref) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GMappedFile, g_mapped_file_unref) @@ -91,3 +96,5 @@ G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GVariantDict, g_variant_dict_clear) G_DEFINE_AUTOPTR_CLEANUP_FUNC(GVariantType, g_variant_type_free) G_DEFINE_AUTO_CLEANUP_FREE_FUNC(GStrv, g_strfreev, NULL) G_DEFINE_AUTOPTR_CLEANUP_FUNC (GRefString, g_ref_string_release) + +G_GNUC_END_IGNORE_DEPRECATIONS diff --git a/glib/gmain.h b/glib/gmain.h index 6325ecbe3..ceb30cbd0 100644 --- a/glib/gmain.h +++ b/glib/gmain.h @@ -430,6 +430,89 @@ GMainContext *g_main_context_get_thread_default (void); GLIB_AVAILABLE_IN_ALL GMainContext *g_main_context_ref_thread_default (void); +/** + * GMainContextPusher: + * + * Opaque type. See g_main_context_pusher_new() for details. + * + * Since: 2.64 + */ +typedef void GMainContextPusher GLIB_AVAILABLE_TYPE_IN_2_64; + +/** + * g_main_context_pusher_new: + * @main_context: (transfer none): a main context to push + * + * Push @main_context as the new thread-default main context for the current + * thread, using g_main_context_push_thread_default(), and return a new + * #GMainContextPusher. Pop with g_main_context_pusher_free(). Using + * g_main_context_pop_thread_default() on @main_context while a + * #GMainContextPusher exists for it can lead to undefined behaviour. + * + * Using two #GMainContextPushers in the same scope is not allowed, as it leads + * to an undefined pop order. + * + * This is intended to be used with g_autoptr(). Note that g_autoptr() + * is only available when using GCC or clang, so the following example + * will only work with those compilers: + * |[ + * typedef struct + * { + * ... + * GMainContext *context; + * ... + * } MyObject; + * + * static void + * my_object_do_stuff (MyObject *self) + * { + * g_autoptr(GMainContextPusher) pusher = g_main_context_pusher_new (self->context); + * + * // Code with main context as the thread default here + * + * if (cond) + * // No need to pop + * return; + * + * // Optionally early pop + * g_clear_pointer (&pusher, g_main_context_pusher_free); + * + * // Code with main context no longer the thread default here + * } + * ]| + * + * Returns: (transfer full): a #GMainContextPusher + * Since: 2.64 + */ +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +static inline GMainContextPusher * +g_main_context_pusher_new (GMainContext *main_context) +{ + g_main_context_push_thread_default (main_context); + return (GMainContextPusher *) main_context; +} +G_GNUC_END_IGNORE_DEPRECATIONS + +/** + * g_main_context_pusher_free: + * @pusher: (transfer full): a #GMainContextPusher + * + * Pop @pusher’s main context as the thread default main context. + * See g_main_context_pusher_new() for details. + * + * This will pop the #GMainContext as the current thread-default main context, + * but will not call g_main_context_unref() on it. + * + * Since: 2.64 + */ +G_GNUC_BEGIN_IGNORE_DEPRECATIONS +static inline void +g_main_context_pusher_free (GMainContextPusher *pusher) +{ + g_main_context_pop_thread_default ((GMainContext *) pusher); +} +G_GNUC_END_IGNORE_DEPRECATIONS + /* GMainLoop: */ GLIB_AVAILABLE_IN_ALL diff --git a/glib/tests/autoptr.c b/glib/tests/autoptr.c index 4eed862af..14b95a9cc 100644 --- a/glib/tests/autoptr.c +++ b/glib/tests/autoptr.c @@ -162,6 +162,30 @@ test_g_main_context (void) } static void +test_g_main_context_pusher (void) +{ + GMainContext *context, *old_thread_default; + + context = g_main_context_new (); + old_thread_default = g_main_context_get_thread_default (); + g_assert_false (old_thread_default == context); + + if (TRUE) + { + g_autoptr(GMainContextPusher) val = g_main_context_pusher_new (context); + + /* Check it’s now the thread-default main context */ + g_assert_true (g_main_context_get_thread_default () == context); + } + + /* Check it’s now the old thread-default main context */ + g_assert_false (g_main_context_get_thread_default () == context); + g_assert_true (g_main_context_get_thread_default () == old_thread_default); + + g_main_context_unref (context); +} + +static void test_g_main_loop (void) { g_autoptr(GMainLoop) val = g_main_loop_new (NULL, TRUE); @@ -692,6 +716,7 @@ main (int argc, gchar *argv[]) g_test_add_func ("/autoptr/g_ptr_array", test_g_ptr_array); g_test_add_func ("/autoptr/g_byte_array", test_g_byte_array); g_test_add_func ("/autoptr/g_main_context", test_g_main_context); + g_test_add_func ("/autoptr/g_main_context_pusher", test_g_main_context_pusher); g_test_add_func ("/autoptr/g_main_loop", test_g_main_loop); g_test_add_func ("/autoptr/g_source", test_g_source); g_test_add_func ("/autoptr/g_mapped_file", test_g_mapped_file); |