summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <slomo@coaxion.net>2019-10-24 11:58:34 +0000
committerSebastian Dröge <slomo@coaxion.net>2019-10-24 11:58:34 +0000
commit2e9b2761d673c0efd477d83a0f0796966abf58f1 (patch)
tree7460a5bf224dfc6dd9f0ed2933af29189a8d445a
parent05be19b9f71fb6a8ae89b06cf672b6a26cd0965f (diff)
parent21f8f8982020dfd65d8d20a5fd0ace67a6dee856 (diff)
downloadglib-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.txt5
-rw-r--r--glib/glib-autocleanups.h7
-rw-r--r--glib/gmain.h83
-rw-r--r--glib/tests/autoptr.c25
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);