Blame programming-guidelines/es/main-contexts.page

Packit 1470ea
Packit 1470ea
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" xmlns:xi="http://www.w3.org/2003/XInclude" type="topic" id="main-contexts" xml:lang="es">
Packit 1470ea
Packit 1470ea
  <info>
Packit 1470ea
    <link type="guide" xref="index#specific-how-tos"/>
Packit 1470ea
Packit 1470ea
    <credit type="author copyright">
Packit 1470ea
      <name>Philip Withnall</name>
Packit 1470ea
      <email its:translate="no">philip.withnall@collabora.co.uk</email>
Packit 1470ea
      <years>2014–2015</years>
Packit 1470ea
    </credit>
Packit 1470ea
Packit 1470ea
    <include xmlns="http://www.w3.org/2001/XInclude" href="cc-by-sa-3-0.xml"/>
Packit 1470ea
Packit 1470ea
    <desc>
Packit 1470ea
      GLib main contexts, invoking functions in other threads, and the event
Packit 1470ea
      loop
Packit 1470ea
    </desc>
Packit 1470ea
  
Packit 1470ea
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
Packit 1470ea
      <mal:name>Daniel Mustieles</mal:name>
Packit 1470ea
      <mal:email>daniel.mustieles@gmail.com</mal:email>
Packit 1470ea
      <mal:years>2016</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  
Packit 1470ea
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
Packit 1470ea
      <mal:name>Javier Mazorra</mal:name>
Packit 1470ea
      <mal:email>mazi.debian@gmail.com</mal:email>
Packit 1470ea
      <mal:years>2016</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  </info>
Packit 1470ea
Packit 1470ea
  <title>GLib Main Contexts</title>
Packit 1470ea
Packit 1470ea
  <synopsis>
Packit 1470ea
    <title>Resumen</title>
Packit 1470ea
Packit 1470ea
    <list>
Packit 1470ea
      <item>

Packit 1470ea
        Use
Packit 1470ea
        <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-main-context-invoke-full">g_main_context_invoke_full()</link>
Packit 1470ea
        to invoke functions in other threads, assuming every thread has a thread
Packit 1470ea
        default main context which runs throughout the lifetime of that thread
Packit 1470ea
        (<link xref="#g-main-context-invoke-full"/>)
Packit 1470ea
      

</item>
Packit 1470ea
      <item>

Packit 1470ea
        Use
Packit 1470ea
        <link href="https://developer.gnome.org/gio/stable/GTask.html">GTask</link>
Packit 1470ea
        to run a function in the background without caring about the specific
Packit 1470ea
        thread used (<link xref="#gtask"/>)
Packit 1470ea
      

</item>
Packit 1470ea
      <item>

Packit 1470ea
        Liberally use assertions to check which context executes each function,
Packit 1470ea
        and add these assertions when first writing the code
Packit 1470ea
        (<link xref="#checking-threading"/>)
Packit 1470ea
      

</item>
Packit 1470ea
      <item>

Packit 1470ea
        Explicitly document contexts a function is expected to be called in, a
Packit 1470ea
        callback will be invoked in, or a signal will be emitted in
Packit 1470ea
        (<link xref="#using-gmaincontext-in-a-library"/>)
Packit 1470ea
      

</item>
Packit 1470ea
      <item>

Packit 1470ea
        Beware of g_idle_add() and similar functions which
Packit 1470ea
        implicitly use the global-default main context
Packit 1470ea
        (<link xref="#implicit-use-of-the-global-default-main-context"/>)
Packit 1470ea
      

</item>
Packit 1470ea
    </list>
Packit 1470ea
  </synopsis>
Packit 1470ea
Packit 1470ea
  <section id="what-is-gmaincontext">
Packit 1470ea
    <title>¿Qué es GMainContext?</title>
Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#GMainContext">GMainContext</link>
Packit 1470ea
      is a generalized implementation of an
Packit 1470ea
      <link href="http://en.wikipedia.org/wiki/Event_loop">event loop</link>,
Packit 1470ea
      useful for implementing polled file I/O or event-based widget systems
Packit 1470ea
      (such as GTK+). It is at the core of almost every GLib application. To
Packit 1470ea
      understand GMainContext requires understanding
Packit 1470ea
      <link href="man:poll(2)">poll()</link> and polled I/O.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      A GMainContext has a set of
Packit 1470ea
      <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#GSource">GSource</link>s
Packit 1470ea
      which are ‘attached’ to it, each of which can be thought of as an expected
Packit 1470ea
      event with an associated callback function which will be invoked when that
Packit 1470ea
      event is received; or equivalently as a set of file descriptors (FDs) to
Packit 1470ea
      check. An event could be a timeout or data being received on a socket, for
Packit 1470ea
      example. One iteration of the event loop will:
Packit 1470ea
    

Packit 1470ea
    <list type="enumerated">
Packit 1470ea
      <item>

Packit 1470ea
        Prepare sources, determining if any of them are ready to dispatch
Packit 1470ea
        immediately.
Packit 1470ea
      

</item>
Packit 1470ea
      <item>

Packit 1470ea
        Poll the sources, blocking the current thread until an event is received
Packit 1470ea
        for one of the sources.
Packit 1470ea
      

</item>
Packit 1470ea
      <item>

Packit 1470ea
        Check which of the sources received an event (several could have).
Packit 1470ea
      

</item>
Packit 1470ea
      <item>

Packit 1470ea
        Dispatch callbacks from those sources.
Packit 1470ea
      

</item>
Packit 1470ea
    </list>
Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      This is
Packit 1470ea
      <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#mainloop-states">explained
Packit 1470ea
      very well</link> in the
Packit 1470ea
      <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#GSourceFuncs">GLib
Packit 1470ea
      documentation</link>.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      At its core, GMainContext is just a poll() loop,
Packit 1470ea
      with the preparation, check and dispatch stages of the loop corresponding
Packit 1470ea
      to the normal preamble and postamble in a typical poll() loop
Packit 1470ea
      implementation, such as listing 1 from
Packit 1470ea
      <link href="http://www.linux-mag.com/id/357/">this article</link>.
Packit 1470ea
      Typically, some complexity is needed in non-trivial
Packit 1470ea
      poll()-using applications to track the lists of FDs which are
Packit 1470ea
      being polled. Additionally, GMainContext adds a lot of useful
Packit 1470ea
      functionality which vanilla poll() doesn’t support. Most
Packit 1470ea
      importantly, it adds thread safety.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      GMainContext is completely thread safe, meaning that a
Packit 1470ea
      GSource can be created in one thread and attached to a
Packit 1470ea
      GMainContext running in another thread. (See
Packit 1470ea
      also: <link xref="threading"/>.) A typical use for this might be to allow
Packit 1470ea
      worker threads to control which sockets are being listened to by a
Packit 1470ea
      GMainContext in a central I/O thread. Each
Packit 1470ea
      GMainContext is ‘acquired’ by a thread for each iteration
Packit 1470ea
      it’s put through. Other threads cannot iterate a GMainContext
Packit 1470ea
      without acquiring it, which guarantees that a GSource and its
Packit 1470ea
      FDs will only be polled by one thread at once (since each
Packit 1470ea
      GSource is attached to at most one
Packit 1470ea
      GMainContext). A GMainContext can be swapped
Packit 1470ea
      between threads across iterations, but this is expensive.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      GMainContext is used instead of poll() mostly
Packit 1470ea
      for convenience, as it transparently handles dynamically managing
Packit 1470ea
      the array of FDs to pass to poll(), especially when operating
Packit 1470ea
      over multiple threads. This is done by encapsulating FDs in
Packit 1470ea
      GSources, which decide whether those FDs should be passed to
Packit 1470ea
      the poll() call on each ‘prepare’ stage of the main context
Packit 1470ea
      iteration.
Packit 1470ea
    

Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="what-is-gmainloop">
Packit 1470ea
    <title>¿Qué es GMainLoop?</title>
Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#GMainLoop">GMainLoop</link>
Packit 1470ea
      is essentially the following few lines of code, once reference counting
Packit 1470ea
      and locking have been removed (from
Packit 1470ea
      <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-main-loop-run">g_main_loop_run()</link>):
Packit 1470ea
    

Packit 1470ea
    loop->is_running = TRUE;
Packit 1470ea
while (loop->is_running)
Packit 1470ea
  {
Packit 1470ea
    g_main_context_iteration (context, TRUE);
Packit 1470ea
  }
Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      Plus a fourth line in
Packit 1470ea
      <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-main-loop-quit">g_main_loop_quit()</link>
Packit 1470ea
      which sets loop->is_running = FALSE and which will cause
Packit 1470ea
      the loop to terminate once the current main context iteration ends.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      Hence, GMainLoop is a convenient, thread-safe way of running
Packit 1470ea
      a GMainContext to process events until a desired exit
Packit 1470ea
      condition is met, at which point g_main_loop_quit() should be
Packit 1470ea
      called. Typically, in a UI program, this will be the user clicking ‘exit’.
Packit 1470ea
      In a socket handling program, this might be the final socket closing.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      It is important not to confuse main contexts with main loops. Main
Packit 1470ea
      contexts do the bulk of the work: preparing source lists, waiting for
Packit 1470ea
      events, and dispatching callbacks. A main loop simply iterates a context.
Packit 1470ea
    

Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="default-contexts">
Packit 1470ea
    <title>Contextos predeterminados</title>
Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      One of the important features of GMainContext is its support
Packit 1470ea
      for ‘default’ contexts. There are two levels of default context: the
Packit 1470ea
      thread-default, and the global-default. The global-default (accessed using
Packit 1470ea
      g_main_context_default()) is run by GTK+ when
Packit 1470ea
      gtk_main() is called. It’s also used for timeouts
Packit 1470ea
      (g_timeout_add()) and idle callbacks
Packit 1470ea
      (g_idle_add()) — these won’t be dispatched unless the default
Packit 1470ea
      context is running! (See:
Packit 1470ea
      <link xref="#implicit-use-of-the-global-default-main-context"/>.)
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      Thread-default contexts are a later addition to GLib (since version 2.22),
Packit 1470ea
      and are generally used for I/O operations which need to run and dispatch
Packit 1470ea
      callbacks in a thread. By calling
Packit 1470ea
      g_main_context_push_thread_default() before starting an I/O
Packit 1470ea
      operation, the thread-default context is set and the I/O operation can add
Packit 1470ea
      its sources to that context. The context can then be run in a new main
Packit 1470ea
      loop in an I/O thread, causing the callbacks to be dispatched on that
Packit 1470ea
      thread’s stack rather than on the stack of the thread running the
Packit 1470ea
      global-default main context. This allows I/O operations to be run entirely
Packit 1470ea
      in a separate thread without explicitly passing a specific
Packit 1470ea
      GMainContext pointer around everywhere.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      Conversely, by starting a long-running operation with a specific
Packit 1470ea
      thread-default context set, the calling code can guarantee that the
Packit 1470ea
      operation’s callbacks will be emitted in that context, even if the
Packit 1470ea
      operation itself runs in a worker thread. This is the principle behind
Packit 1470ea
      <link href="https://developer.gnome.org/gio/stable/GTask.html">GTask</link>:
Packit 1470ea
      when a new GTask is created, it stores a reference to the
Packit 1470ea
      current thread-default context, and dispatches its completion callback in
Packit 1470ea
      that context, even if the task itself is run using
Packit 1470ea
      <link href="https://developer.gnome.org/gio/stable/GTask.html#g-task-run-in-thread">g_task_run_in_thread()</link>.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    <example>
Packit 1470ea
      

Packit 1470ea
        For example, the code below will run a GTask which performs
Packit 1470ea
        two writes in parallel from a thread. The callbacks for the writes will
Packit 1470ea
        be dispatched in the worker thread, whereas the callback from the task
Packit 1470ea
        as a whole will be dispatched in the interesting_context.
Packit 1470ea
      

Packit 1470ea
Packit 1470ea
      
Packit 1470ea
typedef struct {
Packit 1470ea
  GMainLoop *main_loop;
Packit 1470ea
  guint n_remaining;
Packit 1470ea
} WriteData;
Packit 1470ea
Packit 1470ea
/* This is always called in the same thread as thread_cb() because
Packit 1470ea
 * it’s always dispatched in the @worker_context. */
Packit 1470ea
static void
Packit 1470ea
write_cb (GObject      *source_object,
Packit 1470ea
          GAsyncResult *result,
Packit 1470ea
          gpointer      user_data)
Packit 1470ea
{
Packit 1470ea
  WriteData *data = user_data;
Packit 1470ea
  GOutputStream *stream = G_OUTPUT_STREAM (source_object);
Packit 1470ea
  GError *error = NULL;
Packit 1470ea
  gssize len;
Packit 1470ea
Packit 1470ea
  /* Finish the write. */
Packit 1470ea
  len = g_output_stream_write_finish (stream, result, &error);
Packit 1470ea
  if (error != NULL)
Packit 1470ea
    {
Packit 1470ea
      g_error ("Error: %s", error->message);
Packit 1470ea
      g_error_free (error);
Packit 1470ea
    }
Packit 1470ea
Packit 1470ea
  /* Check whether all parallel operations have finished. */
Packit 1470ea
  write_data->n_remaining--;
Packit 1470ea
Packit 1470ea
  if (write_data->n_remaining == 0)
Packit 1470ea
    {
Packit 1470ea
      g_main_loop_quit (write_data->main_loop);
Packit 1470ea
    }
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
/* This is called in a new thread. */
Packit 1470ea
static void
Packit 1470ea
thread_cb (GTask        *task,
Packit 1470ea
           gpointer      source_object,
Packit 1470ea
           gpointer      task_data,
Packit 1470ea
           GCancellable *cancellable)
Packit 1470ea
{
Packit 1470ea
  /* These streams come from somewhere else in the program: */
Packit 1470ea
  GOutputStream *output_stream1, *output_stream;
Packit 1470ea
  GMainContext *worker_context;
Packit 1470ea
  GBytes *data;
Packit 1470ea
  const guint8 *buf;
Packit 1470ea
  gsize len;
Packit 1470ea
Packit 1470ea
  /* Set up a worker context for the writes’ callbacks. */
Packit 1470ea
  worker_context = g_main_context_new ();
Packit 1470ea
  g_main_context_push_thread_default (worker_context);
Packit 1470ea
Packit 1470ea
  /* Set up the writes. */
Packit 1470ea
  write_data.n_remaining = 2;
Packit 1470ea
  write_data.main_loop = g_main_loop_new (worker_context, FALSE);
Packit 1470ea
Packit 1470ea
  data = g_task_get_task_data (task);
Packit 1470ea
  buf = g_bytes_get_data (data, &len);
Packit 1470ea
Packit 1470ea
  g_output_stream_write_async (output_stream1, buf, len,
Packit 1470ea
                               G_PRIORITY_DEFAULT, NULL, write_cb,
Packit 1470ea
                               &write_data);
Packit 1470ea
  g_output_stream_write_async (output_stream2, buf, len,
Packit 1470ea
                               G_PRIORITY_DEFAULT, NULL, write_cb,
Packit 1470ea
                               &write_data);
Packit 1470ea
Packit 1470ea
  /* Run the main loop until both writes have finished. */
Packit 1470ea
  g_main_loop_run (write_data.main_loop);
Packit 1470ea
  g_task_return_boolean (task, TRUE);  /* ignore errors */
Packit 1470ea
Packit 1470ea
  g_main_loop_unref (write_data.main_loop);
Packit 1470ea
Packit 1470ea
  g_main_context_pop_thread_default (worker_context);
Packit 1470ea
  g_main_context_unref (worker_context);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
/* This can be called from any thread. Its @callback will always be
Packit 1470ea
 * dispatched in the thread which currently owns
Packit 1470ea
 * @interesting_context. */
Packit 1470ea
void
Packit 1470ea
parallel_writes_async (GBytes              *data,
Packit 1470ea
                       GMainContext        *interesting_context,
Packit 1470ea
                       GCancellable        *cancellable,
Packit 1470ea
                       GAsyncReadyCallback  callback,
Packit 1470ea
                       gpointer             user_data)
Packit 1470ea
{
Packit 1470ea
  GTask *task;
Packit 1470ea
Packit 1470ea
  g_main_context_push_thread_default (interesting_context);
Packit 1470ea
Packit 1470ea
  task = g_task_new (NULL, cancellable, callback, user_data);
Packit 1470ea
  g_task_set_task_data (task, data,
Packit 1470ea
                        (GDestroyNotify) g_bytes_unref);
Packit 1470ea
  g_task_run_in_thread (task, thread_cb);
Packit 1470ea
  g_object_unref (task);
Packit 1470ea
Packit 1470ea
  g_main_context_pop_thread_default (interesting_context);
Packit 1470ea
}
Packit 1470ea
    </example>
Packit 1470ea
Packit 1470ea
    <section id="implicit-use-of-the-global-default-main-context">
Packit 1470ea
      <title>Implicit Use of the Global-Default Main Context</title>
Packit 1470ea
Packit 1470ea
      

Packit 1470ea
        Several functions implicitly add sources to the global-default main
Packit 1470ea
        context. They should not be used in threaded code. Instead, use
Packit 1470ea
        g_source_attach() with the GSource created by
Packit 1470ea
        the replacement function from the table below.
Packit 1470ea
      

Packit 1470ea
Packit 1470ea
      

Packit 1470ea
        Implicit use of the global-default main context means the callback
Packit 1470ea
        functions are invoked in the main thread, typically resulting in work
Packit 1470ea
        being brought back from a worker thread into the main thread.
Packit 1470ea
      

Packit 1470ea
Packit 1470ea
      
Packit 1470ea
        
Packit 1470ea
        
Packit 1470ea
        
Packit 1470ea
          
Packit 1470ea
            

No use

Packit 1470ea
            

Use en su lugar

Packit 1470ea
          
Packit 1470ea
        
Packit 1470ea
        
Packit 1470ea
          
Packit 1470ea
            

g_timeout_add()

Packit 1470ea
            

g_timeout_source_new()

Packit 1470ea
          
Packit 1470ea
          
Packit 1470ea
            

g_idle_add()

Packit 1470ea
            

g_idle_source_new()

Packit 1470ea
          
Packit 1470ea
          
Packit 1470ea
            

g_child_watch_add()

Packit 1470ea
            

g_child_watch_source_new()

Packit 1470ea
          
Packit 1470ea
        
Packit 1470ea
      
Packit 1470ea
Packit 1470ea
      <example>
Packit 1470ea
        

Packit 1470ea
          So to delay some computation in a worker thread, use the following
Packit 1470ea
          code:
Packit 1470ea
        

Packit 1470ea
        
Packit 1470ea
static guint
Packit 1470ea
schedule_computation (guint delay_seconds)
Packit 1470ea
{
Packit 1470ea
  GSource *source = NULL;
Packit 1470ea
  GMainContext *context;
Packit 1470ea
  guint id;
Packit 1470ea
Packit 1470ea
  /* Get the calling context. */
Packit 1470ea
  context = g_main_context_get_thread_default ();
Packit 1470ea
Packit 1470ea
  source = g_timeout_source_new_seconds (delay_seconds);
Packit 1470ea
  g_source_set_callback (source, do_computation, NULL, NULL);
Packit 1470ea
  id = g_source_attach (source, context);
Packit 1470ea
  g_source_unref (source);
Packit 1470ea
Packit 1470ea
  /* The ID can be used with the same @context to
Packit 1470ea
   * cancel the scheduled computation if needed. */
Packit 1470ea
  return id;
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
static void
Packit 1470ea
do_computation (gpointer user_data)
Packit 1470ea
{
Packit 1470ea
  /* … */
Packit 1470ea
}
Packit 1470ea
      </example>
Packit 1470ea
    </section>
Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="using-gmaincontext-in-a-library">
Packit 1470ea
    <title>Usar GMainContext en una biblioteca</title>
Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      At a high level, library code must not make changes to main contexts which
Packit 1470ea
      could affect the execution of an application using the library, for
Packit 1470ea
      example by changing when the application’s GSources are
Packit 1470ea
      dispatched. There are various best practices which can be followed to aid
Packit 1470ea
      this.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      Never iterate a context created outside the library, including the
Packit 1470ea
      global-default or thread-default contexts. Otherwise,
Packit 1470ea
      GSources created in the application may be dispatched
Packit 1470ea
      when the application is not expecting it, causing
Packit 1470ea
      <link href="http://en.wikipedia.org/wiki/Reentrancy_%28computing%29">re-entrancy
Packit 1470ea
      problems</link> for the application code.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      Always remove GSources from a main context before dropping
Packit 1470ea
      the library’s last reference to the context, especially if it may have
Packit 1470ea
      been exposed to the application (for example, as a thread-default).
Packit 1470ea
      Otherwise the application may keep a reference to the main context and
Packit 1470ea
      continue iterating it after the library has returned, potentially causing
Packit 1470ea
      unexpected source dispatches in the library. This is equivalent to not
Packit 1470ea
      assuming that dropping the library’s last reference to a main context will
Packit 1470ea
      finalize that context.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      If the library is designed to be used from multiple threads, or in a
Packit 1470ea
      context-aware fashion, always document which context each callback will be
Packit 1470ea
      dispatched in. For example, “callbacks will always be dispatched in the
Packit 1470ea
      context which is the thread-default at the time of the object’s
Packit 1470ea
      construction”. Developers using the library’s API need to know this
Packit 1470ea
      information.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      Use g_main_context_invoke() to ensure callbacks are
Packit 1470ea
      dispatched in the right context. It’s much easier than manually using
Packit 1470ea
      g_idle_source_new() to transfer work between contexts.
Packit 1470ea
      (See: <link xref="#ensuring-functions-are-called-in-the-right-context"/>.)
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      Libraries should never use g_main_context_default() (or,
Packit 1470ea
      equivalently, pass NULL to a GMainContext-typed
Packit 1470ea
      parameter). Always store and explicitly use a specific
Packit 1470ea
      GMainContext, even if it often points to some default
Packit 1470ea
      context. This makes the code easier to split out into threads in future,
Packit 1470ea
      if needed, without causing hard-to-debug problems caused by callbacks
Packit 1470ea
      being invoked in the wrong context.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      Always write things asynchronously internally (using
Packit 1470ea
      <link xref="#gtask">GTask</link> where appropriate), and keep
Packit 1470ea
      synchronous wrappers at the very top level of an API, where they can be
Packit 1470ea
      implemented by calling g_main_context_iteration() on a
Packit 1470ea
      specific GMainContext. Again, this makes future refactoring
Packit 1470ea
      easier. This is demonstrated in the above example: the thread uses
Packit 1470ea
      g_output_stream_write_async() rather than
Packit 1470ea
      g_output_stream_write().
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      Always match pushes and pops of the thread-default main context:
Packit 1470ea
      g_main_context_push_thread_default() and
Packit 1470ea
      g_main_context_pop_thread_default().
Packit 1470ea
    

Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="ensuring-functions-are-called-in-the-right-context">
Packit 1470ea
    <title>Ensuring Functions are Called in the Right Context</title>
Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      The ‘right context’ is the thread-default main context of the thread
Packit 1470ea
      the function should be executing in. This assumes the typical case
Packit 1470ea
      that every thread has a single main context running in a main
Packit 1470ea
      loop. A main context effectively provides a work or
Packit 1470ea
      <link href="http://en.wikipedia.org/wiki/Message_queue">message
Packit 1470ea
      queue</link> for the thread — something which the thread can
Packit 1470ea
      periodically check to determine if there is work pending from
Packit 1470ea
      another thread. Putting a message on this queue – invoking a function in
Packit 1470ea
      another main context – will result in it eventually being dispatched in
Packit 1470ea
      that thread.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    <example>
Packit 1470ea
      

Packit 1470ea
        For example, if an application does a long and CPU-intensive computation
Packit 1470ea
        it should schedule this in a background thread so that UI updates in the
Packit 1470ea
        main thread are not blocked. The results of the computation, however,
Packit 1470ea
        might need to be displayed in the UI, so some UI update function must be
Packit 1470ea
        called in the main thread once the computation’s complete.
Packit 1470ea
      

Packit 1470ea
Packit 1470ea
      

Packit 1470ea
        Furthermore, if the computation function can be limited to a single
Packit 1470ea
        thread, it becomes easy to eliminate the need for locking a lot of the
Packit 1470ea
        data it accesses. This assumes that other threads are implemented
Packit 1470ea
        similarly and hence most data is only accessed by a single thread, with
Packit 1470ea
        threads communicating by
Packit 1470ea
        <link href="http://en.wikipedia.org/wiki/Message_passing">message
Packit 1470ea
        passing</link>. This allows each thread to update its data at its
Packit 1470ea
        leisure, which significantly simplifies locking.
Packit 1470ea
     

Packit 1470ea
   </example>
Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      For some functions, there might be no reason to care which context they’re
Packit 1470ea
      executed in, perhaps because they’re asynchronous and hence do not block
Packit 1470ea
      the context. However, it is still advisable to be explicit about which
Packit 1470ea
      context is used, since those functions may emit signals or invoke
Packit 1470ea
      callbacks, and for reasons of thread safety it’s necessary to know which
Packit 1470ea
      threads those signal handlers or callbacks are going to be invoked in.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    <example>
Packit 1470ea
      

Packit 1470ea
        For example, the progress callback in
Packit 1470ea
        <link href="https://developer.gnome.org/gio/stable/GFile.html#g-file-copy-async">g_file_copy_async()</link>
Packit 1470ea
        is documented as being called in the thread-default main context
Packit 1470ea
        at the time of the initial call.
Packit 1470ea
      

Packit 1470ea
    </example>
Packit 1470ea
Packit 1470ea
    <section id="invocation-core-principle">
Packit 1470ea
      <title>Principles of Invocation</title>
Packit 1470ea
Packit 1470ea
      

Packit 1470ea
        The core principle of invoking a function in a specific context is
Packit 1470ea
        simple, and is walked through below to explain the concepts. In practice
Packit 1470ea
        the <link xref="#g-main-context-invoke-full">convenience method,
Packit 1470ea
        g_main_context_invoke_full()</link> should be used instead.
Packit 1470ea
      

Packit 1470ea
Packit 1470ea
      

Packit 1470ea
        A
Packit 1470ea
        <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#GSource">GSource</link>
Packit 1470ea
        has to be added to the target GMainContext, which will invoke
Packit 1470ea
        the function when it’s dispatched. This GSource should almost
Packit 1470ea
        always be an idle source created with
Packit 1470ea
        <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-idle-source-new">g_idle_source_new()</link>,
Packit 1470ea
        but this doesn’t have to be the case. It could be a timeout source
Packit 1470ea
        so that the function is executed after a delay, for example.
Packit 1470ea
      

Packit 1470ea
Packit 1470ea
      

Packit 1470ea
        The GSource will be
Packit 1470ea
        <link xref="#what-is-gmaincontext">dispatched as soon as it’s ready</link>,
Packit 1470ea
        calling the function on the thread’s stack. In the case of an idle source,
Packit 1470ea
        this will be as soon as all sources at a higher priority have been
Packit 1470ea
        dispatched — this can be tweaked using the idle source’s priority
Packit 1470ea
        parameter with
Packit 1470ea
        <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-source-set-priority">g_source_set_priority()</link>.
Packit 1470ea
        The source will typically then be destroyed so the function is only
Packit 1470ea
        executed once (though again, this doesn’t have to be the case).
Packit 1470ea
      

Packit 1470ea
Packit 1470ea
      

Packit 1470ea
        Data can be passed between threads as the user_data passed to
Packit 1470ea
        the GSource’s callback. This is set on the source using
Packit 1470ea
        <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-source-set-callback">g_source_set_callback()</link>,
Packit 1470ea
        along with the callback function to invoke. Only a single pointer
Packit 1470ea
        is provided, so if multiple data fields need passing, they must be wrapped
Packit 1470ea
        in an allocated structure.
Packit 1470ea
      

Packit 1470ea
Packit 1470ea
      <example>
Packit 1470ea
        

Packit 1470ea
          The example below demonstrates the underlying principles, but there are
Packit 1470ea
          convenience methods explained below which simplify things.
Packit 1470ea
        

Packit 1470ea
Packit 1470ea
        
Packit 1470ea
/* Main function for the background thread, thread1. */
Packit 1470ea
static gpointer
Packit 1470ea
thread1_main (gpointer user_data)
Packit 1470ea
{
Packit 1470ea
  GMainContext *thread1_main_context = user_data;
Packit 1470ea
  GMainLoop *main_loop;
Packit 1470ea
Packit 1470ea
  /* Set up the thread’s context and run it forever. */
Packit 1470ea
  g_main_context_push_thread_default (thread1_main_context);
Packit 1470ea
Packit 1470ea
  main_loop = g_main_loop_new (thread1_main_context, FALSE);
Packit 1470ea
  g_main_loop_run (main_loop);
Packit 1470ea
  g_main_loop_unref (main_loop);
Packit 1470ea
Packit 1470ea
  g_main_context_pop_thread_default (thread1_main_context);
Packit 1470ea
  g_main_context_unref (thread1_main_context);
Packit 1470ea
Packit 1470ea
  return NULL;
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
/* A data closure structure to carry multiple variables between
Packit 1470ea
 * threads. */
Packit 1470ea
typedef struct {
Packit 1470ea
  gchar   *some_string;  /* owned */
Packit 1470ea
  guint    some_int;
Packit 1470ea
  GObject *some_object;  /* owned */
Packit 1470ea
} MyFuncData;
Packit 1470ea
Packit 1470ea
static void
Packit 1470ea
my_func_data_free (MyFuncData *data)
Packit 1470ea
{
Packit 1470ea
  g_free (data->some_string);
Packit 1470ea
  g_clear_object (&data->some_object);
Packit 1470ea
  g_free (data);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
static void
Packit 1470ea
my_func (const gchar *some_string,
Packit 1470ea
         guint        some_int,
Packit 1470ea
         GObject     *some_object)
Packit 1470ea
{
Packit 1470ea
  /* Do something long and CPU intensive! */
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
/* Convert an idle callback into a call to my_func(). */
Packit 1470ea
static gboolean
Packit 1470ea
my_func_idle (gpointer user_data)
Packit 1470ea
{
Packit 1470ea
  MyFuncData *data = user_data;
Packit 1470ea
Packit 1470ea
  my_func (data->some_string, data->some_int, data->some_object);
Packit 1470ea
Packit 1470ea
  return G_SOURCE_REMOVE;
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
/* Function to be called in the main thread to schedule a call to
Packit 1470ea
 * my_func() in thread1, passing the given parameters along. */
Packit 1470ea
static void
Packit 1470ea
invoke_my_func (GMainContext *thread1_main_context,
Packit 1470ea
                const gchar  *some_string,
Packit 1470ea
                guint         some_int,
Packit 1470ea
                GObject      *some_object)
Packit 1470ea
{
Packit 1470ea
  GSource *idle_source;
Packit 1470ea
  MyFuncData *data;
Packit 1470ea
Packit 1470ea
  /* Create a data closure to pass all the desired variables
Packit 1470ea
   * between threads. */
Packit 1470ea
  data = g_new0 (MyFuncData, 1);
Packit 1470ea
  data->some_string = g_strdup (some_string);
Packit 1470ea
  data->some_int = some_int;
Packit 1470ea
  data->some_object = g_object_ref (some_object);
Packit 1470ea
Packit 1470ea
  /* Create a new idle source, set my_func() as the callback with
Packit 1470ea
   * some data to be passed between threads, bump up the priority
Packit 1470ea
   * and schedule it by attaching it to thread1’s context. */
Packit 1470ea
  idle_source = g_idle_source_new ();
Packit 1470ea
  g_source_set_callback (idle_source, my_func_idle, data,
Packit 1470ea
                         (GDestroyNotify) my_func_data_free);
Packit 1470ea
  g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
Packit 1470ea
  g_source_attach (idle_source, thread1_main_context);
Packit 1470ea
  g_source_unref (idle_source);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
/* Main function for the main thread. */
Packit 1470ea
static void
Packit 1470ea
main (void)
Packit 1470ea
{
Packit 1470ea
  GThread *thread1;
Packit 1470ea
  GMainContext *thread1_main_context;
Packit 1470ea
Packit 1470ea
  /* Spawn a background thread and pass it a reference to its
Packit 1470ea
   * GMainContext. Retain a reference for use in this thread
Packit 1470ea
   * too. */
Packit 1470ea
  thread1_main_context = g_main_context_new ();
Packit 1470ea
  g_thread_new ("thread1", thread1_main,
Packit 1470ea
                g_main_context_ref (thread1_main_context));
Packit 1470ea
Packit 1470ea
  /* Maybe set up your UI here, for example. */
Packit 1470ea
Packit 1470ea
  /* Invoke my_func() in the other thread. */
Packit 1470ea
  invoke_my_func (thread1_main_context,
Packit 1470ea
                  "some data which needs passing between threads",
Packit 1470ea
                  123456, some_object);
Packit 1470ea
Packit 1470ea
  /* Continue doing other work. */
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
        

Packit 1470ea
          This invocation is uni-directional: it calls
Packit 1470ea
          my_func() in thread1, but there’s no way to
Packit 1470ea
          return a value to the main thread. To do that, the same principle needs
Packit 1470ea
          to be used again, invoking a callback function in the main thread. It’s
Packit 1470ea
          a straightforward extension which isn’t covered here.
Packit 1470ea
        

Packit 1470ea
Packit 1470ea
        

Packit 1470ea
          To maintain thread safety, data which is potentially accessed by
Packit 1470ea
          multiple threads must make those accesses mutually exclusive using a
Packit 1470ea
          <link href="http://en.wikipedia.org/wiki/Mutual_exclusion">mutex</link>.
Packit 1470ea
          Data potentially accessed by multiple threads:
Packit 1470ea
          thread1_main_context, passed in the fork call to
Packit 1470ea
          thread1_main; and some_object, a reference to
Packit 1470ea
          which is passed in the data closure. Critically, GLib guarantees that
Packit 1470ea
          GMainContext is thread safe, so sharing
Packit 1470ea
          thread1_main_context between threads is safe. The example
Packit 1470ea
          assumes that other code accessing some_object is thread
Packit 1470ea
          safe.
Packit 1470ea
        

Packit 1470ea
Packit 1470ea
        

Packit 1470ea
          Note that some_string and some_int cannot be
Packit 1470ea
          accessed from both threads, because copies of them are passed
Packit 1470ea
          to thread1, rather than the originals. This is a standard
Packit 1470ea
          technique for making cross-thread calls thread safe without requiring
Packit 1470ea
          locking. It also avoids the problem of synchronizing freeing
Packit 1470ea
          some_string.
Packit 1470ea
        

Packit 1470ea
Packit 1470ea
        

Packit 1470ea
          Similarly, a reference to some_object is transferred to
Packit 1470ea
          thread1, which works around the issue of synchronizing
Packit 1470ea
          destruction of the object (see <link xref="memory-management"/>).
Packit 1470ea
        

Packit 1470ea
Packit 1470ea
        

Packit 1470ea
          g_idle_source_new() is used rather than the simpler
Packit 1470ea
          g_idle_add() so the GMainContext to attach to
Packit 1470ea
          can be specified.
Packit 1470ea
        

Packit 1470ea
      </example>
Packit 1470ea
    </section>
Packit 1470ea
Packit 1470ea
    <section id="g-main-context-invoke-full">
Packit 1470ea
      <title>
Packit 1470ea
        Convenience Method: g_main_context_invoke_full()
Packit 1470ea
      </title>
Packit 1470ea
Packit 1470ea
      

Packit 1470ea
        This is simplified greatly by the convenience method,
Packit 1470ea
        <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-main-context-invoke-full">g_main_context_invoke_full()</link>.
Packit 1470ea
        It invokes a callback so that the specified GMainContext is
Packit 1470ea
        owned during the invocation. Owning a main context is almost always
Packit 1470ea
        equivalent to running it, and hence the function is invoked in the
Packit 1470ea
        thread for which the specified context is the thread-default.
Packit 1470ea
      

Packit 1470ea
Packit 1470ea
      

Packit 1470ea
        g_main_context_invoke() can be used instead if the user
Packit 1470ea
        data does not need to be freed by a GDestroyNotify callback
Packit 1470ea
        after the invocation returns.
Packit 1470ea
      

Packit 1470ea
Packit 1470ea
      <example>
Packit 1470ea
        

Packit 1470ea
          Modifying the earlier example, the invoke_my_func()
Packit 1470ea
          function can be replaced by the following:
Packit 1470ea
        

Packit 1470ea
Packit 1470ea
        
Packit 1470ea
static void
Packit 1470ea
invoke_my_func (GMainContext *thread1_main_context,
Packit 1470ea
                const gchar  *some_string,
Packit 1470ea
                guint         some_int,
Packit 1470ea
                GObject      *some_object)
Packit 1470ea
{
Packit 1470ea
  MyFuncData *data;
Packit 1470ea
Packit 1470ea
  /* Create a data closure to pass all the desired variables
Packit 1470ea
   * between threads. */
Packit 1470ea
  data = g_new0 (MyFuncData, 1);
Packit 1470ea
  data->some_string = g_strdup (some_string);
Packit 1470ea
  data->some_int = some_int;
Packit 1470ea
  data->some_object = g_object_ref (some_object);
Packit 1470ea
Packit 1470ea
  /* Invoke the function. */
Packit 1470ea
  g_main_context_invoke_full (thread1_main_context,
Packit 1470ea
                              G_PRIORITY_DEFAULT, my_func_idle,
Packit 1470ea
                              data,
Packit 1470ea
                              (GDestroyNotify) my_func_data_free);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
        

Packit 1470ea
          Consider what happens if invoke_my_func() were called
Packit 1470ea
          from thread1, rather than from the main thread. With the
Packit 1470ea
          original implementation, the idle source would be added to
Packit 1470ea
          thread1’s context and dispatched on the context’s next
Packit 1470ea
          iteration (assuming no pending dispatches with higher priorities).
Packit 1470ea
          With the improved implementation,
Packit 1470ea
          g_main_context_invoke_full() will notice that the
Packit 1470ea
          specified context is already owned by the thread (or ownership can be
Packit 1470ea
          acquired by it), and will call my_func_idle() directly,
Packit 1470ea
          rather than attaching a source to the context and delaying the
Packit 1470ea
          invocation to the next context iteration.
Packit 1470ea
        

Packit 1470ea
Packit 1470ea
        

Packit 1470ea
          This subtle behavior difference doesn’t matter in most cases, but is
Packit 1470ea
          worth bearing in mind since it can affect blocking behavior
Packit 1470ea
          (invoke_my_func() would go from taking negligible time,
Packit 1470ea
          to taking the same amount of time as my_func() before
Packit 1470ea
          returning).
Packit 1470ea
        

Packit 1470ea
      </example>
Packit 1470ea
    </section>
Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="checking-threading">
Packit 1470ea
    <title>Comprobar los hilos</title>
Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      It is useful to document which thread each function should be called in,
Packit 1470ea
      in the form of an assertion:
Packit 1470ea
    

Packit 1470ea
    
Packit 1470ea
g_assert (g_main_context_is_owner (expected_main_context));
Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      If that’s put at the top of each function, any assertion failure will
Packit 1470ea
      highlight a case where a function has been called from the wrong
Packit 1470ea
      thread. It is much easier to write these assertions when initially
Packit 1470ea
      developing code, rather than debugging race conditions which can easily
Packit 1470ea
      result from a function being called in the wrong thread.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      This technique can also be applied to signal emissions and callbacks,
Packit 1470ea
      improving type safety as well as asserting the right context is used. Note
Packit 1470ea
      that signal emission via
Packit 1470ea
      <link href="https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-emit">g_signal_emit()</link>
Packit 1470ea
      is synchronous, and doesn’t involve a main context at all.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    <example>
Packit 1470ea
      

Packit 1470ea
        For example, instead of using the following when emitting a signal:
Packit 1470ea
      

Packit 1470ea
      
Packit 1470ea
guint param1;  /* arbitrary example parameters */
Packit 1470ea
gchar *param2;
Packit 1470ea
guint retval = 0;
Packit 1470ea
Packit 1470ea
g_signal_emit_by_name (my_object, "some-signal",
Packit 1470ea
                       param1, param2, &retval);
Packit 1470ea
Packit 1470ea
      

Se puede usar lo siguiente:

Packit 1470ea
      
Packit 1470ea
static guint
Packit 1470ea
emit_some_signal (GObject     *my_object,
Packit 1470ea
                  guint        param1,
Packit 1470ea
                  const gchar *param2)
Packit 1470ea
{
Packit 1470ea
  guint retval = 0;
Packit 1470ea
Packit 1470ea
  g_assert (g_main_context_is_owner (expected_main_context));
Packit 1470ea
Packit 1470ea
  g_signal_emit_by_name (my_object, "some-signal",
Packit 1470ea
                         param1, param2, &retval);
Packit 1470ea
Packit 1470ea
  return retval;
Packit 1470ea
}
Packit 1470ea
    </example>
Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="gtask">
Packit 1470ea
    <title>GTask</title>
Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      <link href="https://developer.gnome.org/gio/stable/GTask.html">GTask</link>
Packit 1470ea
      provides a slightly different approach to invoking functions in other
Packit 1470ea
      threads, which is more suited to the case where a function should be
Packit 1470ea
      executed in some background thread, but not a specific one.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      GTask takes a data closure and a function to execute, and
Packit 1470ea
      provides ways to return the result from this function. It handles
Packit 1470ea
      everything necessary to run that function in an arbitrary thread belonging
Packit 1470ea
      to some thread pool internal to GLib.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    <example>
Packit 1470ea
      

Packit 1470ea
        By combining
Packit 1470ea
        <link xref="#g-main-context-invoke-full">g_main_context_invoke_full()</link>
Packit 1470ea
        and GTask, it is possible to run a task in a specific context
Packit 1470ea
        and effortlessly return its result to the current context:
Packit 1470ea
      

Packit 1470ea
      
Packit 1470ea
/* This will be invoked in thread1. */
Packit 1470ea
static gboolean
Packit 1470ea
my_func_idle (gpointer user_data)
Packit 1470ea
{
Packit 1470ea
  GTask *task = G_TASK (user_data);
Packit 1470ea
  MyFuncData *data;
Packit 1470ea
  gboolean retval;
Packit 1470ea
Packit 1470ea
  /* Call my_func() and propagate its returned boolean to
Packit 1470ea
   * the main thread. */
Packit 1470ea
  data = g_task_get_task_data (task);
Packit 1470ea
  retval = my_func (data->some_string, data->some_int,
Packit 1470ea
                    data->some_object);
Packit 1470ea
  g_task_return_boolean (task, retval);
Packit 1470ea
Packit 1470ea
  return G_SOURCE_REMOVE;
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
/* Whichever thread this is invoked in, the @callback will be
Packit 1470ea
 * invoked in, once my_func() has finished and returned a result. */
Packit 1470ea
static void
Packit 1470ea
invoke_my_func_with_result (GMainContext        *thread1_main_context,
Packit 1470ea
                            const gchar         *some_string,
Packit 1470ea
                            guint                some_int,
Packit 1470ea
                            GObject             *some_object,
Packit 1470ea
                            GAsyncReadyCallback  callback,
Packit 1470ea
                            gpointer             user_data)
Packit 1470ea
{
Packit 1470ea
  MyFuncData *data;
Packit 1470ea
Packit 1470ea
  /* Create a data closure to pass all the desired variables
Packit 1470ea
   * between threads. */
Packit 1470ea
  data = g_new0 (MyFuncData, 1);
Packit 1470ea
  data->some_string = g_strdup (some_string);
Packit 1470ea
  data->some_int = some_int;
Packit 1470ea
  data->some_object = g_object_ref (some_object);
Packit 1470ea
Packit 1470ea
  /* Create a GTask to handle returning the result to the current
Packit 1470ea
   * thread-default main context. */
Packit 1470ea
  task = g_task_new (NULL, NULL, callback, user_data);
Packit 1470ea
  g_task_set_task_data (task, data,
Packit 1470ea
                        (GDestroyNotify) my_func_data_free);
Packit 1470ea
Packit 1470ea
  /* Invoke the function. */
Packit 1470ea
  g_main_context_invoke_full (thread1_main_context,
Packit 1470ea
                              G_PRIORITY_DEFAULT, my_func_idle,
Packit 1470ea
                              task,
Packit 1470ea
                              (GDestroyNotify) g_object_unref);
Packit 1470ea
}
Packit 1470ea
    </example>
Packit 1470ea
  </section>
Packit 1470ea
</page>