mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 15:06:14 +01:00
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
This commit is contained in:
parent
90381ecdbd
commit
4363f1932f
@ -462,6 +462,11 @@ g_main_depth
|
||||
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
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
144
glib/gmain.c
144
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 */
|
||||
|
||||
/**
|
||||
|
@ -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: */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user