Blame programming-guidelines/pt_BR/threading.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="threading" xml:lang="pt-BR">
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>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>Movendo computação da thread principal para threads de trabalho</desc>
Packit 1470ea
  
Packit 1470ea
    <mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
Packit 1470ea
      <mal:name>Rafael Fontenelle</mal:name>
Packit 1470ea
      <mal:email>rafaelff@gnome.org</mal:email>
Packit 1470ea
      <mal:years>2017</mal:years>
Packit 1470ea
    </mal:credit>
Packit 1470ea
  </info>
Packit 1470ea
Packit 1470ea
  <title>Threading</title>
Packit 1470ea
Packit 1470ea
  <synopsis>
Packit 1470ea
    <title>Resumo</title>
Packit 1470ea
Packit 1470ea
    <list>
Packit 1470ea
      <item>

Packit 1470ea
        Do not use threads if at all possible.
Packit 1470ea
        (<link xref="#when-to-use-threading"/>)
Packit 1470ea
      

</item>
Packit 1470ea
      <item>

Packit 1470ea
        If threads have to be used, use GTask or
Packit 1470ea
        GThreadPool and isolate the threaded code as much as
Packit 1470ea
        possible.
Packit 1470ea
        (<link xref="#using-threading"/>)
Packit 1470ea
      

</item>
Packit 1470ea
      <item>

Packit 1470ea
        Use g_thread_join() to avoid leaking thread resources if
Packit 1470ea
        using GThread manually.
Packit 1470ea
        (<link xref="#using-threading"/>)
Packit 1470ea
      

</item>
Packit 1470ea
      <item>

Packit 1470ea
        Be careful about the GMainContext which code is executed in
Packit 1470ea
        if using threads. Executing code in the wrong context can cause race
Packit 1470ea
        conditions, or block the main loop.
Packit 1470ea
        (<link xref="#using-threading"/>)
Packit 1470ea
      

</item>
Packit 1470ea
    </list>
Packit 1470ea
  </synopsis>
Packit 1470ea
Packit 1470ea
  <section id="when-to-use-threading">
Packit 1470ea
    <title>When to Use Threading</title>
Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      When writing projects using GLib, the default approach should be to
Packit 1470ea
      never use threads. Instead, make proper use of the
Packit 1470ea
      <link xref="main-contexts">GLib main context</link> which, through the use
Packit 1470ea
      of asynchronous operations,
Packit 1470ea
      allows most blocking I/O operations to continue in the background while
Packit 1470ea
      the main context continues to process other events. Analysis, review and
Packit 1470ea
      debugging of threaded code becomes very hard, very quickly.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      Threading should only be necessary when using an external library which
Packit 1470ea
      has blocking functions which need to be called from GLib code. If the
Packit 1470ea
      library provides a non-blocking alternative, or one which integrates with
Packit 1470ea
      a
Packit 1470ea
      <link href="http://pubs.opengroup.org/onlinepubs/009695399/functions/poll.html">poll()</link>
Packit 1470ea
      loop, that should be used in preference. If the blocking function really
Packit 1470ea
      must be used, a thin wrapper should be written for it to convert it to the
Packit 1470ea
      normal
Packit 1470ea
      <link href="https://developer.gnome.org/gio/stable/GAsyncResult.html">GAsyncResult
Packit 1470ea
      style</link> of GLib asynchronous function, running the blocking operation
Packit 1470ea
      in a worker thread.
Packit 1470ea
    

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

Por exemplo:

Packit 1470ea
      
Packit 1470ea
int
Packit 1470ea
some_blocking_function (void *param1,
Packit 1470ea
                        void *param2);
Packit 1470ea
Packit 1470ea
      

Packit 1470ea
        Should be wrapped as:
Packit 1470ea
      

Packit 1470ea
      
Packit 1470ea
void
Packit 1470ea
some_blocking_function_async (void                 *param1,
Packit 1470ea
                              void                 *param2,
Packit 1470ea
                              GCancellable         *cancellable,
Packit 1470ea
                              GAsyncReadyCallback   callback,
Packit 1470ea
                              gpointer              user_data);
Packit 1470ea
int
Packit 1470ea
some_blocking_function_finish (GAsyncResult        *result,
Packit 1470ea
                               GError             **error);
Packit 1470ea
Packit 1470ea
Packit 1470ea
      

Packit 1470ea
        With an implementation something like:
Packit 1470ea
      

Packit 1470ea
      /* Closure for the call’s parameters. */
Packit 1470ea
typedef struct {
Packit 1470ea
  void *param1;
Packit 1470ea
  void *param2;
Packit 1470ea
} SomeBlockingFunctionData;
Packit 1470ea
Packit 1470ea
static void
Packit 1470ea
some_blocking_function_data_free (SomeBlockingFunctionData *data)
Packit 1470ea
{
Packit 1470ea
  free_param (data->param1);
Packit 1470ea
  free_param (data->param2);
Packit 1470ea
Packit 1470ea
  g_free (data);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
static void
Packit 1470ea
some_blocking_function_thread_cb (GTask         *task,
Packit 1470ea
                                  gpointer       source_object,
Packit 1470ea
                                  gpointer       task_data,
Packit 1470ea
                                  GCancellable  *cancellable)
Packit 1470ea
{
Packit 1470ea
  SomeBlockingFunctionData *data = task_data;
Packit 1470ea
  int retval;
Packit 1470ea
Packit 1470ea
  /* Handle cancellation. */
Packit 1470ea
  if (g_task_return_error_if_cancelled (task))
Packit 1470ea
    {
Packit 1470ea
      return;
Packit 1470ea
    }
Packit 1470ea
Packit 1470ea
  /* Run the blocking function. */
Packit 1470ea
  retval = some_blocking_function (data->param1, data->param2);
Packit 1470ea
  g_task_return_int (task, retval);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
void
Packit 1470ea
some_blocking_function_async (void                 *param1,
Packit 1470ea
                              void                 *param2,
Packit 1470ea
                              GCancellable         *cancellable,
Packit 1470ea
                              GAsyncReadyCallback   callback,
Packit 1470ea
                              gpointer              user_data)
Packit 1470ea
{
Packit 1470ea
  GTask *task = NULL;  /* owned */
Packit 1470ea
  SomeBlockingFunctionData *data = NULL;  /* owned */
Packit 1470ea
Packit 1470ea
  g_return_if_fail (validate_param (param1));
Packit 1470ea
  g_return_if_fail (validate_param (param2));
Packit 1470ea
  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
Packit 1470ea
Packit 1470ea
  task = g_task_new (NULL, cancellable, callback, user_data);
Packit 1470ea
  g_task_set_source_tag (task, some_blocking_function_async);
Packit 1470ea
Packit 1470ea
  /* Cancellation should be handled manually using mechanisms specific to
Packit 1470ea
   * some_blocking_function(). */
Packit 1470ea
  g_task_set_return_on_cancel (task, FALSE);
Packit 1470ea
Packit 1470ea
  /* Set up a closure containing the call’s parameters. Copy them to avoid
Packit 1470ea
   * locking issues between the calling thread and the worker thread. */
Packit 1470ea
  data = g_new0 (SomeBlockingFunctionData, 1);
Packit 1470ea
  data->param1 = copy_param (param1);
Packit 1470ea
  data->param2 = copy_param (param2);
Packit 1470ea
Packit 1470ea
  g_task_set_task_data (task, data, some_blocking_function_data_free);
Packit 1470ea
Packit 1470ea
  /* Run the task in a worker thread and return immediately while that continues
Packit 1470ea
   * in the background. When it’s done it will call @callback in the current
Packit 1470ea
   * thread default main context. */
Packit 1470ea
  g_task_run_in_thread (task, some_blocking_function_thread_cb);
Packit 1470ea
Packit 1470ea
  g_object_unref (task);
Packit 1470ea
}
Packit 1470ea
Packit 1470ea
int
Packit 1470ea
some_blocking_function_finish (GAsyncResult  *result,
Packit 1470ea
                               GError       **error)
Packit 1470ea
{
Packit 1470ea
  g_return_val_if_fail (g_task_is_valid (result,
Packit 1470ea
                                         some_blocking_function_async), -1);
Packit 1470ea
  g_return_val_if_fail (error == NULL || *error == NULL, -1);
Packit 1470ea
Packit 1470ea
  return g_task_propagate_int (G_TASK (result), error);
Packit 1470ea
}
Packit 1470ea
      

Packit 1470ea
        See the
Packit 1470ea
        <link href="https://developer.gnome.org/gio/stable/GAsyncResult.html">GAsyncResult
Packit 1470ea
        documentation</link> for more details. A simple way to implement the
Packit 1470ea
        worker thread is to use
Packit 1470ea
        <link href="https://developer.gnome.org/gio/stable/GTask.html">GTask</link>
Packit 1470ea
        and <link href="https://developer.gnome.org/gio/stable/GTask.html#g-task-run-in-thread">g_task_run_in_thread()</link>.
Packit 1470ea
        (See also: <link xref="main-contexts#gtask"/>.)
Packit 1470ea
      

Packit 1470ea
    </example>
Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="using-threading">
Packit 1470ea
    <title>Using Threading</title>
Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      If GTask is not suitable for writing the worker thread, a
Packit 1470ea
      more low-level approach must be used. This should be considered very
Packit 1470ea
      carefully, as it is very easy to get threading code wrong in ways which
Packit 1470ea
      will unpredictably cause bugs at runtime, cause deadlocks, or consume too
Packit 1470ea
      many resources and terminate the program.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      A full manual on writing threaded code is beyond the scope of this
Packit 1470ea
      document, but here are a number of guidelines to follow which should
Packit 1470ea
      reduce the potential for bugs in threading code. The overriding principle
Packit 1470ea
      is to reduce the amount of code and data which can be affected by
Packit 1470ea
      threading — for example, reducing the number of threads, the complexity of
Packit 1470ea
      worker thread implementation, and the amount of data shared between
Packit 1470ea
      threads.
Packit 1470ea
    

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

Packit 1470ea
          Use <link href="https://developer.gnome.org/glib/stable/glib-Thread-Pools.html">GThreadPool</link>
Packit 1470ea
          instead of manually creating
Packit 1470ea
          <link href="https://developer.gnome.org/glib/stable/glib-Threads.html">GThreads</link>
Packit 1470ea
          if possible. GThreadPool supports a work queue, limits on
Packit 1470ea
          the number of spawned threads, and automatically joins finished
Packit 1470ea
          threads so they are not leaked.
Packit 1470ea
        

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

Packit 1470ea
          If it is not possible to use a GThreadPool (which is
Packit 1470ea
          rarely the case):
Packit 1470ea
        

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

Packit 1470ea
              Use <link href="https://developer.gnome.org/glib/stable/glib-Threads.html#g-thread-try-new">g_thread_try_new()</link>
Packit 1470ea
              to spawn threads, instead of
Packit 1470ea
              <link href="https://developer.gnome.org/glib/stable/glib-Threads.html#g-thread-new">g_thread_new()</link>,
Packit 1470ea
              so errors due to the system running out of threads can be handled
Packit 1470ea
              gracefully rather than unconditionally aborting the program.
Packit 1470ea
            

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

Packit 1470ea
              Explicitly join threads using
Packit 1470ea
              <link href="https://developer.gnome.org/glib/stable/glib-Threads.html#g-thread-join">g_thread_join()</link>
Packit 1470ea
              to avoid leaking the thread resources.
Packit 1470ea
            

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

Packit 1470ea
          Use message passing to transfer data between threads, rather than
Packit 1470ea
          manual locking with mutexes. GThreadPool explicitly
Packit 1470ea
          supports this with
Packit 1470ea
          <link href="https://developer.gnome.org/glib/stable/glib-Thread-Pools.html#g-thread-pool-push">g_thread_pool_push()</link>.
Packit 1470ea
        

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

Packit 1470ea
          If mutexes must be used:
Packit 1470ea
        

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

Packit 1470ea
              Isolate threading code as much as possible, keeping mutexes
Packit 1470ea
              private within classes, and tightly bound to very specific class
Packit 1470ea
              members.
Packit 1470ea
            

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

Packit 1470ea
              All mutexes should be clearly commented beside their declaration,
Packit 1470ea
              indicating which other structures or variables they protect access
Packit 1470ea
              to. Similarly, those variables should be commented saying that
Packit 1470ea
              they should only be accessed with that mutex held.
Packit 1470ea
            

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

Packit 1470ea
          Be careful about interactions between main contexts and threads. For
Packit 1470ea
          example,
Packit 1470ea
          <link href="https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#g-timeout-add-seconds">g_timeout_add_seconds()</link>
Packit 1470ea
          adds a timeout to be executed in the global default main
Packit 1470ea
          context, which is being run in the main thread, not
Packit 1470ea
          necessarily the current thread. Getting this wrong can mean that
Packit 1470ea
          work intended for a worker thread accidentally ends up being executed
Packit 1470ea
          in the main thread anyway. (See also:
Packit 1470ea
          <link xref="main-contexts#default-contexts"/>.)
Packit 1470ea
        

Packit 1470ea
      </item>
Packit 1470ea
    </list>
Packit 1470ea
  </section>
Packit 1470ea
Packit 1470ea
  <section id="debugging">
Packit 1470ea
    <title>Depuração</title>
Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      Debugging threading issues is tricky, both because they are hard to
Packit 1470ea
      reproduce, and because they are hard to reason about. This is one of the
Packit 1470ea
      big reasons for avoiding using threads in the first place.
Packit 1470ea
    

Packit 1470ea
Packit 1470ea
    

Packit 1470ea
      However, if a threading issue does arise,
Packit 1470ea
      <link xref="tooling#helgrind-and-drd">Valgrind’s drd and helgrind tools
Packit 1470ea
      are useful</link>.
Packit 1470ea
    

Packit 1470ea
  </section>
Packit 1470ea
</page>