[glib] Add g_main_context_push_thread_default() etc
- From: Dan Winship <danw src gnome org>
- To: svn-commits-list gnome org
- Subject: [glib] Add g_main_context_push_thread_default() etc
- Date: Wed, 1 Jul 2009 13:05:56 +0000 (UTC)
commit 4363f1932f1be4474a81d5b9cf8a58c91b682868
Author: Dan Winship <danw gnome org>
Date: Thu Jun 4 21:59:15 2009 -0400
Add g_main_context_push_thread_default() etc
This allows applications to use async methods from other threads, or
in multiple independent main loops.
http://bugzilla.gnome.org/show_bug.cgi?id=579984
docs/reference/glib/glib-sections.txt | 5 +
docs/reference/glib/tmpl/main.sgml | 24 ++++++
glib/glib.symbols | 3 +
glib/gmain.c | 144 ++++++++++++++++++++++++++++++++-
glib/gmain.h | 5 +
5 files changed, 177 insertions(+), 4 deletions(-)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index 0a583ed..bec08ad 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -463,6 +463,11 @@ g_main_current_source
g_main_set_poll_func
<SUBSECTION>
+g_main_context_get_thread_default
+g_main_context_push_thread_default
+g_main_context_pop_thread_default
+
+<SUBSECTION>
g_timeout_source_new
g_timeout_source_new_seconds
g_timeout_add
diff --git a/docs/reference/glib/tmpl/main.sgml b/docs/reference/glib/tmpl/main.sgml
index 9f7de38..0e5a142 100644
--- a/docs/reference/glib/tmpl/main.sgml
+++ b/docs/reference/glib/tmpl/main.sgml
@@ -545,6 +545,30 @@ for the default main context.
@Deprecated: 2.2: Use g_main_context_set_poll_func() instead.
+<!-- ##### FUNCTION g_main_context_get_thread_default ##### -->
+<para>
+
+</para>
+
+ Returns:
+
+
+<!-- ##### FUNCTION g_main_context_push_thread_default ##### -->
+<para>
+
+</para>
+
+ context:
+
+
+<!-- ##### FUNCTION g_main_context_pop_thread_default ##### -->
+<para>
+
+</para>
+
+ context:
+
+
<!-- ##### FUNCTION g_timeout_source_new ##### -->
<para>
diff --git a/glib/glib.symbols b/glib/glib.symbols
index 8bcd899..0bd7ab9 100644
--- a/glib/glib.symbols
+++ b/glib/glib.symbols
@@ -622,11 +622,14 @@ g_main_context_find_source_by_funcs_user_data
g_main_context_find_source_by_id
g_main_context_find_source_by_user_data
g_main_context_get_poll_func
+g_main_context_get_thread_default
g_main_context_is_owner
g_main_context_iteration
g_main_context_new
g_main_context_pending
+g_main_context_pop_thread_default
g_main_context_prepare
+g_main_context_push_thread_default
g_main_context_query
g_main_context_ref
g_main_context_release
diff --git a/glib/gmain.c b/glib/gmain.c
index 6d6b594..e04c7b5 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -529,11 +529,12 @@ g_main_context_new (void)
/**
* g_main_context_default:
*
- * Returns the default main context. This is the main context used
- * for main loop functions when a main loop is not explicitly
- * specified.
+ * Returns the global default main context. This is the main context
+ * used for main loop functions when a main loop is not explicitly
+ * specified, and corresponds to the "main" main loop. See also
+ * g_main_context_get_thread_default().
*
- * Return value: the default main context.
+ * Return value: the global default main context.
**/
GMainContext *
g_main_context_default (void)
@@ -556,6 +557,141 @@ g_main_context_default (void)
return default_main_context;
}
+static GStaticPrivate thread_context_stack = G_STATIC_PRIVATE_INIT;
+
+static void
+free_context_stack (gpointer data)
+{
+ GQueue *stack = data;
+ GMainContext *context;
+
+ while (!g_queue_is_empty (stack))
+ {
+ context = g_queue_pop_head (stack);
+ g_main_context_release (context);
+ if (context)
+ g_main_context_unref (context);
+ }
+ g_queue_free (stack);
+}
+
+/**
+ * g_main_context_push_thread_default:
+ * @context: a #GMainContext, or %NULL for the global default context
+ *
+ * Acquires @context and sets it as the thread-default context for the
+ * current thread. This will cause certain asynchronous operations
+ * (such as most <link linkend="gio">gio</link>-based I/O) which are
+ * started in this thread to run under @context and deliver their
+ * results to its main loop, rather than running under the global
+ * default context in the main thread. Note that calling this function
+ * changes the context returned by
+ * g_main_context_get_thread_default(), <emphasis>not</emphasis> the
+ * one returned by g_main_context_default(), so it does not affect the
+ * context used by functions like g_idle_add().
+ *
+ * Normally you would call this function shortly after creating a new
+ * thread, passing it a #GMainContext which will be run by a
+ * #GMainLoop in that thread, to set a new default context for all
+ * async operations in that thread. (In this case, you don't need to
+ * ever call g_main_context_pop_thread_default().) In some cases
+ * however, you may want to schedule a single operation in a
+ * non-default context, or temporarily use a non-default context in
+ * the main thread. In that case, you can wrap the call to the
+ * asynchronous operation inside a
+ * g_main_context_push_thread_default() /
+ * g_main_context_pop_thread_default() pair, but it is up to you to
+ * ensure that no other asynchronous operations accidentally get
+ * started while the non-default context is active.
+ *
+ * Beware that libraries that predate this function may not correctly
+ * handle being used from a thread with a thread-default context. Eg,
+ * see g_file_supports_thread_contexts().
+ *
+ * Since: 2.22
+ **/
+void
+g_main_context_push_thread_default (GMainContext *context)
+{
+ GQueue *stack;
+ gboolean acquired_context;
+
+ acquired_context = g_main_context_acquire (context);
+ g_return_if_fail (acquired_context);
+
+ if (context == g_main_context_default ())
+ context = NULL;
+ else if (context)
+ g_main_context_ref (context);
+
+ stack = g_static_private_get (&thread_context_stack);
+ if (!stack)
+ {
+ stack = g_queue_new ();
+ g_static_private_set (&thread_context_stack, stack,
+ free_context_stack);
+ }
+
+ g_queue_push_head (stack, context);
+}
+
+/**
+ * g_main_context_pop_thread_default:
+ * @context: a #GMainContext object, or %NULL
+ *
+ * Pops @context off the thread-default context stack (verifying that
+ * it was on the top of the stack).
+ *
+ * Since: 2.22
+ **/
+void
+g_main_context_pop_thread_default (GMainContext *context)
+{
+ GQueue *stack;
+
+ if (context == g_main_context_default ())
+ context = NULL;
+
+ stack = g_static_private_get (&thread_context_stack);
+
+ g_return_if_fail (stack != NULL);
+ g_return_if_fail (g_queue_peek_head (stack) == context);
+
+ g_queue_pop_head (stack);
+
+ g_main_context_release (context);
+ if (context)
+ g_main_context_unref (context);
+}
+
+/**
+ * g_main_context_get_thread_default:
+ *
+ * Gets the thread-default #GMainContext for this thread. Asynchronous
+ * operations that want to be able to be run in contexts other than
+ * the default one should call this method to get a #GMainContext to
+ * add their #GSource<!-- -->s to. (Note that even in single-threaded
+ * programs applications may sometimes want to temporarily push a
+ * non-default context, so it is not safe to assume that this will
+ * always return %NULL if threads are not initialized.)
+ *
+ * Returns: the thread-default #GMainContext, or %NULL if the
+ * thread-default context is the global default context.
+ *
+ * Since: 2.22
+ **/
+GMainContext *
+g_main_context_get_thread_default (void)
+{
+ GQueue *stack;
+
+ stack = g_static_private_get (&thread_context_stack);
+ if (stack)
+ return g_queue_peek_head (stack);
+ else
+ return NULL;
+}
+
/* Hooks for adding to the main loop */
/**
diff --git a/glib/gmain.h b/glib/gmain.h
index 3f0e9cd..15fe54e 100644
--- a/glib/gmain.h
+++ b/glib/gmain.h
@@ -158,6 +158,11 @@ void g_main_context_remove_poll (GMainContext *context,
gint g_main_depth (void);
GSource *g_main_current_source (void);
+/* GMainContexts for other threads
+ */
+void g_main_context_push_thread_default (GMainContext *context);
+void g_main_context_pop_thread_default (GMainContext *context);
+GMainContext *g_main_context_get_thread_default (void);
/* GMainLoop: */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]