mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 15:36:17 +01:00
GTask: convert long desc to markdown
Use markdown sections and lists here.
This commit is contained in:
parent
ed2bb95330
commit
ba307a0c52
264
gio/gtask.c
264
gio/gtask.c
@ -30,29 +30,27 @@
|
|||||||
* @include: gio/gio.h
|
* @include: gio/gio.h
|
||||||
* @see_also: #GAsyncResult
|
* @see_also: #GAsyncResult
|
||||||
*
|
*
|
||||||
* <para>
|
* A #GTask represents and manages a cancellable "task".
|
||||||
* A #GTask represents and manages a cancellable "task".
|
*
|
||||||
* </para>
|
* ## Asynchronous operations
|
||||||
* <refsect2>
|
*
|
||||||
* <title>Asynchronous operations</title>
|
* The most common usage of #GTask is as a #GAsyncResult, to
|
||||||
* <para>
|
* manage data during an asynchronous operation. You call
|
||||||
* The most common usage of #GTask is as a #GAsyncResult, to
|
* g_task_new() in the "start" method, followed by
|
||||||
* manage data during an asynchronous operation. You call
|
* g_task_set_task_data() and the like if you need to keep some
|
||||||
* g_task_new() in the "start" method, followed by
|
* additional data associated with the task, and then pass the
|
||||||
* g_task_set_task_data() and the like if you need to keep some
|
* task object around through your asynchronous operation.
|
||||||
* additional data associated with the task, and then pass the
|
* Eventually, you will call a method such as
|
||||||
* task object around through your asynchronous operation.
|
* g_task_return_pointer() or g_task_return_error(), which will
|
||||||
* Eventually, you will call a method such as
|
* save the value you give it and then invoke the task's callback
|
||||||
* g_task_return_pointer() or g_task_return_error(), which will
|
* function (waiting until the next iteration of the main
|
||||||
* save the value you give it and then invoke the task's callback
|
* loop first, if necessary). The caller will pass the #GTask back
|
||||||
* function (waiting until the next iteration of the main
|
* to the operation's finish function (as a #GAsyncResult), and
|
||||||
* loop first, if necessary). The caller will pass the #GTask back
|
* you can use g_task_propagate_pointer() or the like to extract
|
||||||
* to the operation's finish function (as a #GAsyncResult), and
|
* the return value.
|
||||||
* you can use g_task_propagate_pointer() or the like to extract
|
*
|
||||||
* the return value.
|
* Here is an example for using GTask as a GAsyncResult:
|
||||||
* </para>
|
* |[
|
||||||
* Here is an example for using GTask as a GAsyncResult:
|
|
||||||
* |[
|
|
||||||
* typedef struct {
|
* typedef struct {
|
||||||
* CakeFrostingType frosting;
|
* CakeFrostingType frosting;
|
||||||
* char *message;
|
* char *message;
|
||||||
@ -145,23 +143,21 @@
|
|||||||
* return g_task_propagate_pointer (G_TASK (result), error);
|
* return g_task_propagate_pointer (G_TASK (result), error);
|
||||||
* }
|
* }
|
||||||
* ]|
|
* ]|
|
||||||
* </refsect2>
|
*
|
||||||
* <refsect2>
|
* ## Chained asynchronous operations
|
||||||
* <title>Chained asynchronous operations</title>
|
*
|
||||||
* <para>
|
* #GTask also tries to simplify asynchronous operations that
|
||||||
* #GTask also tries to simplify asynchronous operations that
|
* internally chain together several smaller asynchronous
|
||||||
* internally chain together several smaller asynchronous
|
* operations. g_task_get_cancellable(), g_task_get_context(), and
|
||||||
* operations. g_task_get_cancellable(), g_task_get_context(), and
|
* g_task_get_priority() allow you to get back the task's
|
||||||
* g_task_get_priority() allow you to get back the task's
|
* #GCancellable, #GMainContext, and <link
|
||||||
* #GCancellable, #GMainContext, and <link
|
* linkend="io-priority">I/O priority</link> when starting a new
|
||||||
* linkend="io-priority">I/O priority</link> when starting a new
|
* subtask, so you don't have to keep track of them yourself.
|
||||||
* subtask, so you don't have to keep track of them yourself.
|
* g_task_attach_source() simplifies the case of waiting for a
|
||||||
* g_task_attach_source() simplifies the case of waiting for a
|
* source to fire (automatically using the correct #GMainContext
|
||||||
* source to fire (automatically using the correct #GMainContext
|
* and priority).
|
||||||
* and priority).
|
*
|
||||||
* </para>
|
* Here is an example for chained asynchronous operations:
|
||||||
* <para>
|
|
||||||
* Here is an example for chained asynchronous operations:
|
|
||||||
* |[
|
* |[
|
||||||
* typedef struct {
|
* typedef struct {
|
||||||
* Cake *cake;
|
* Cake *cake;
|
||||||
@ -288,18 +284,15 @@
|
|||||||
* return g_task_propagate_pointer (G_TASK (result), error);
|
* return g_task_propagate_pointer (G_TASK (result), error);
|
||||||
* }
|
* }
|
||||||
* ]|
|
* ]|
|
||||||
* </para>
|
*
|
||||||
* </refsect2>
|
* ## Asynchronous operations from synchronous ones
|
||||||
* <refsect2>
|
*
|
||||||
* <title>Asynchronous operations from synchronous ones</title>
|
* You can use g_task_run_in_thread() to turn a synchronous
|
||||||
* <para>
|
* operation into an asynchronous one, by running it in a thread
|
||||||
* You can use g_task_run_in_thread() to turn a synchronous
|
* which will then dispatch the result back to the caller's
|
||||||
* operation into an asynchronous one, by running it in a thread
|
* #GMainContext when it completes.
|
||||||
* which will then dispatch the result back to the caller's
|
*
|
||||||
* #GMainContext when it completes.
|
* Running a task in a thread:
|
||||||
* </para>
|
|
||||||
* <para>
|
|
||||||
* Running a task in a thread:
|
|
||||||
* |[
|
* |[
|
||||||
* typedef struct {
|
* typedef struct {
|
||||||
* guint radius;
|
* guint radius;
|
||||||
@ -368,25 +361,22 @@
|
|||||||
* return g_task_propagate_pointer (G_TASK (result), error);
|
* return g_task_propagate_pointer (G_TASK (result), error);
|
||||||
* }
|
* }
|
||||||
* ]|
|
* ]|
|
||||||
* </para>
|
*
|
||||||
* </refsect2>
|
* ## Adding cancellability to uncancellable tasks
|
||||||
* <refsect2>
|
*
|
||||||
* <title>Adding cancellability to uncancellable tasks</title>
|
* Finally, g_task_run_in_thread() and g_task_run_in_thread_sync()
|
||||||
* <para>
|
* can be used to turn an uncancellable operation into a
|
||||||
* Finally, g_task_run_in_thread() and g_task_run_in_thread_sync()
|
* cancellable one. If you call g_task_set_return_on_cancel(),
|
||||||
* can be used to turn an uncancellable operation into a
|
* passing %TRUE, then if the task's #GCancellable is cancelled,
|
||||||
* cancellable one. If you call g_task_set_return_on_cancel(),
|
* it will return control back to the caller immediately, while
|
||||||
* passing %TRUE, then if the task's #GCancellable is cancelled,
|
* allowing the task thread to continue running in the background
|
||||||
* it will return control back to the caller immediately, while
|
* (and simply discarding its result when it finally does finish).
|
||||||
* allowing the task thread to continue running in the background
|
* Provided that the task thread is careful about how it uses
|
||||||
* (and simply discarding its result when it finally does finish).
|
* locks and other externally-visible resources, this allows you
|
||||||
* Provided that the task thread is careful about how it uses
|
* to make "GLib-friendly" asynchronous and cancellable
|
||||||
* locks and other externally-visible resources, this allows you
|
* synchronous variants of blocking APIs.
|
||||||
* to make "GLib-friendly" asynchronous and cancellable
|
*
|
||||||
* synchronous variants of blocking APIs.
|
* Cancelling a task:
|
||||||
* </para>
|
|
||||||
* <para>
|
|
||||||
* Cancelling a task:
|
|
||||||
* |[
|
* |[
|
||||||
* static void
|
* static void
|
||||||
* bake_cake_thread (GTask *task,
|
* bake_cake_thread (GTask *task,
|
||||||
@ -439,7 +429,7 @@
|
|||||||
* GAsyncReadyCallback callback,
|
* GAsyncReadyCallback callback,
|
||||||
* gpointer user_data)
|
* gpointer user_data)
|
||||||
* {
|
* {
|
||||||
* CakeData *cake_data;
|
J* CakeData *cake_data;
|
||||||
* GTask *task;
|
* GTask *task;
|
||||||
*
|
*
|
||||||
* cake_data = g_slice_new (CakeData);
|
* cake_data = g_slice_new (CakeData);
|
||||||
@ -477,80 +467,62 @@
|
|||||||
* return cake;
|
* return cake;
|
||||||
* }
|
* }
|
||||||
* ]|
|
* ]|
|
||||||
* </para>
|
*
|
||||||
* </refsect2>
|
* ## Porting from GSimpleAsyncResult
|
||||||
* <refsect2>
|
*
|
||||||
* <title>Porting from <literal>GSimpleAsyncResult</literal></title>
|
* #GTask's API attempts to be simpler than #GSimpleAsyncResult's
|
||||||
* <para>
|
* in several ways:
|
||||||
* #GTask's API attempts to be simpler than #GSimpleAsyncResult's
|
* - You can save task-specific data with g_task_set_task_data(), and
|
||||||
* in several ways:
|
* retrieve it later with g_task_get_task_data(). This replaces the
|
||||||
* </para>
|
* abuse of g_simple_async_result_set_op_res_gpointer() for the same
|
||||||
* <itemizedlist>
|
* purpose with #GSimpleAsyncResult.
|
||||||
* <listitem><para>
|
* - In addition to the task data, #GTask also keeps track of the
|
||||||
* You can save task-specific data with g_task_set_task_data(), and
|
* <link linkend="io-priority">priority</link>, #GCancellable, and
|
||||||
* retrieve it later with g_task_get_task_data(). This replaces the
|
* #GMainContext associated with the task, so tasks that consist of
|
||||||
* abuse of g_simple_async_result_set_op_res_gpointer() for the same
|
* a chain of simpler asynchronous operations will have easy access
|
||||||
* purpose with #GSimpleAsyncResult.
|
* to those values when starting each sub-task.
|
||||||
* </para></listitem>
|
* - g_task_return_error_if_cancelled() provides simplified
|
||||||
* <listitem><para>
|
* handling for cancellation. In addition, cancellation
|
||||||
* In addition to the task data, #GTask also keeps track of the
|
* overrides any other #GTask return value by default, like
|
||||||
* <link linkend="io-priority">priority</link>, #GCancellable, and
|
* #GSimpleAsyncResult does when
|
||||||
* #GMainContext associated with the task, so tasks that consist of
|
* g_simple_async_result_set_check_cancellable() is called.
|
||||||
* a chain of simpler asynchronous operations will have easy access
|
* (You can use g_task_set_check_cancellable() to turn off that
|
||||||
* to those values when starting each sub-task.
|
* behavior.) On the other hand, g_task_run_in_thread()
|
||||||
* </para></listitem>
|
* guarantees that it will always run your
|
||||||
* <listitem><para>
|
* <literal>task_func</literal>, even if the task's #GCancellable
|
||||||
* g_task_return_error_if_cancelled() provides simplified
|
* is already cancelled before the task gets a chance to run;
|
||||||
* handling for cancellation. In addition, cancellation
|
* you can start your <literal>task_func</literal> with a
|
||||||
* overrides any other #GTask return value by default, like
|
* g_task_return_error_if_cancelled() check if you need the
|
||||||
* #GSimpleAsyncResult does when
|
* old behavior.
|
||||||
* g_simple_async_result_set_check_cancellable() is called.
|
* - The "return" methods (eg, g_task_return_pointer())
|
||||||
* (You can use g_task_set_check_cancellable() to turn off that
|
* automatically cause the task to be "completed" as well, and
|
||||||
* behavior.) On the other hand, g_task_run_in_thread()
|
* there is no need to worry about the "complete" vs "complete
|
||||||
* guarantees that it will always run your
|
* in idle" distinction. (#GTask automatically figures out
|
||||||
* <literal>task_func</literal>, even if the task's #GCancellable
|
* whether the task's callback can be invoked directly, or
|
||||||
* is already cancelled before the task gets a chance to run;
|
* if it needs to be sent to another #GMainContext, or delayed
|
||||||
* you can start your <literal>task_func</literal> with a
|
* until the next iteration of the current #GMainContext.)
|
||||||
* g_task_return_error_if_cancelled() check if you need the
|
* - The "finish" functions for #GTask-based operations are generally
|
||||||
* old behavior.
|
* much simpler than #GSimpleAsyncResult ones, normally consisting
|
||||||
* </para></listitem>
|
* of only a single call to g_task_propagate_pointer() or the like.
|
||||||
* <listitem><para>
|
* Since g_task_propagate_pointer() "steals" the return value from
|
||||||
* The "return" methods (eg, g_task_return_pointer())
|
* the #GTask, it is not necessary to juggle pointers around to
|
||||||
* automatically cause the task to be "completed" as well, and
|
* prevent it from being freed twice.
|
||||||
* there is no need to worry about the "complete" vs "complete
|
* - With #GSimpleAsyncResult, it was common to call
|
||||||
* in idle" distinction. (#GTask automatically figures out
|
* g_simple_async_result_propagate_error() from the
|
||||||
* whether the task's callback can be invoked directly, or
|
* <literal>_finish()</literal> wrapper function, and have
|
||||||
* if it needs to be sent to another #GMainContext, or delayed
|
* virtual method implementations only deal with successful
|
||||||
* until the next iteration of the current #GMainContext.)
|
* returns. This behavior is deprecated, because it makes it
|
||||||
* </para></listitem>
|
* difficult for a subclass to chain to a parent class's async
|
||||||
* <listitem><para>
|
* methods. Instead, the wrapper function should just be a
|
||||||
* The "finish" functions for #GTask-based operations are generally
|
* simple wrapper, and the virtual method should call an
|
||||||
* much simpler than #GSimpleAsyncResult ones, normally consisting
|
* appropriate <literal>g_task_propagate_</literal> function.
|
||||||
* of only a single call to g_task_propagate_pointer() or the like.
|
* Note that wrapper methods can now use
|
||||||
* Since g_task_propagate_pointer() "steals" the return value from
|
* g_async_result_legacy_propagate_error() to do old-style
|
||||||
* the #GTask, it is not necessary to juggle pointers around to
|
* #GSimpleAsyncResult error-returning behavior, and
|
||||||
* prevent it from being freed twice.
|
* g_async_result_is_tagged() to check if a result is tagged as
|
||||||
* </para></listitem>
|
* having come from the <literal>_async()</literal> wrapper
|
||||||
* <listitem><para>
|
* function (for "short-circuit" results, such as when passing
|
||||||
* With #GSimpleAsyncResult, it was common to call
|
* 0 to g_input_stream_read_async()).
|
||||||
* g_simple_async_result_propagate_error() from the
|
|
||||||
* <literal>_finish()</literal> wrapper function, and have
|
|
||||||
* virtual method implementations only deal with successful
|
|
||||||
* returns. This behavior is deprecated, because it makes it
|
|
||||||
* difficult for a subclass to chain to a parent class's async
|
|
||||||
* methods. Instead, the wrapper function should just be a
|
|
||||||
* simple wrapper, and the virtual method should call an
|
|
||||||
* appropriate <literal>g_task_propagate_</literal> function.
|
|
||||||
* Note that wrapper methods can now use
|
|
||||||
* g_async_result_legacy_propagate_error() to do old-style
|
|
||||||
* #GSimpleAsyncResult error-returning behavior, and
|
|
||||||
* g_async_result_is_tagged() to check if a result is tagged as
|
|
||||||
* having come from the <literal>_async()</literal> wrapper
|
|
||||||
* function (for "short-circuit" results, such as when passing
|
|
||||||
* 0 to g_input_stream_read_async()).
|
|
||||||
* </para></listitem>
|
|
||||||
* </itemizedlist>
|
|
||||||
* </refsect2>
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user