Copyright | Will Thompson and Iñaki García Etxebarria |
---|---|
License | LGPL-2.1 |
Maintainer | Iñaki García Etxebarria |
Safe Haskell | None |
Language | Haskell2010 |
- Exported types
- Methods
- getCancellable
- getCheckCancellable
- getCompleted
- getContext
- getName
- getPriority
- getReturnOnCancel
- getSourceObject
- getSourceTag
- getTaskData
- hadError
- isValid
- new
- propagateBoolean
- propagateInt
- propagatePointer
- propagateValue
- reportError
- returnBoolean
- returnError
- returnErrorIfCancelled
- returnInt
- returnNewErrorLiteral
- returnPointer
- returnValue
- runInThread
- runInThreadSync
- setCheckCancellable
- setName
- setPriority
- setReturnOnCancel
- setSourceTag
- setStaticName
- setTaskData
- Properties
A GTask
represents and manages a cancellable ‘task’.
Asynchronous operations
The most common usage of GTask
is as a AsyncResult
, to
manage data during an asynchronous operation. You call
taskNew
in the ‘start’ method, followed by
taskSetTaskData
and the like if you need to keep some
additional data associated with the task, and then pass the
task object around through your asynchronous operation.
Eventually, you will call a method such as
taskReturnPointer
or taskReturnError
, which
will save the value you give it and then invoke the task’s callback
function in the thread-default main context (see
mainContextPushThreadDefault
)
where it was created (waiting until the next iteration of the main
loop first, if necessary). The caller will pass the GTask
back to
the operation’s finish function (as a AsyncResult
), and you can
use taskPropagatePointer
or the like to extract the
return value.
Using GTask
requires the thread-default MainContext
from when
the GTask
was constructed to be running at least until the task has
completed and its data has been freed.
If a GTask
has been constructed and its callback set, it is an error to
not call g_task_return_*()
on it. GLib will warn at runtime if this happens
(since 2.76).
Here is an example for using GTask
as a AsyncResult
:
c code
typedef struct { CakeFrostingType frosting; char *message; } DecorationData; static void decoration_data_free (DecorationData *decoration) { g_free (decoration->message); g_slice_free (DecorationData, decoration); } static void baked_cb (Cake *cake, gpointer user_data) { GTask *task = user_data; DecorationData *decoration = g_task_get_task_data (task); GError *error = NULL; if (cake == NULL) { g_task_return_new_error (task, BAKER_ERROR, BAKER_ERROR_NO_FLOUR, "Go to the supermarket"); g_object_unref (task); return; } if (!cake_decorate (cake, decoration->frosting, decoration->message, &error)) { g_object_unref (cake); // g_task_return_error() takes ownership of error g_task_return_error (task, error); g_object_unref (task); return; } g_task_return_pointer (task, cake, g_object_unref); g_object_unref (task); } void baker_bake_cake_async (Baker *self, guint radius, CakeFlavor flavor, CakeFrostingType frosting, const char *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task; DecorationData *decoration; Cake *cake; task = g_task_new (self, cancellable, callback, user_data); if (radius < 3) { g_task_return_new_error (task, BAKER_ERROR, BAKER_ERROR_TOO_SMALL, "%ucm radius cakes are silly", radius); g_object_unref (task); return; } cake = _baker_get_cached_cake (self, radius, flavor, frosting, message); if (cake != NULL) { // _baker_get_cached_cake() returns a reffed cake g_task_return_pointer (task, cake, g_object_unref); g_object_unref (task); return; } decoration = g_slice_new (DecorationData); decoration->frosting = frosting; decoration->message = g_strdup (message); g_task_set_task_data (task, decoration, (GDestroyNotify) decoration_data_free); _baker_begin_cake (self, radius, flavor, cancellable, baked_cb, task); } Cake * baker_bake_cake_finish (Baker *self, GAsyncResult *result, GError **error) { g_return_val_if_fail (g_task_is_valid (result, self), NULL); return g_task_propagate_pointer (G_TASK (result), error); }
Chained asynchronous operations
GTask
also tries to simplify asynchronous operations that
internally chain together several smaller asynchronous
operations. taskGetCancellable
, taskGetContext
,
and taskGetPriority
allow you to get back the task’s
Cancellable
, MainContext
, and
I/O priority
when starting a new subtask, so you don’t have to keep track
of them yourself. Task
.attach_source
() simplifies the case
of waiting for a source to fire (automatically using the correct
MainContext
and priority).
Here is an example for chained asynchronous operations:
c code
typedef struct { Cake *cake; CakeFrostingType frosting; char *message; } BakingData; static void decoration_data_free (BakingData *bd) { if (bd->cake) g_object_unref (bd->cake); g_free (bd->message); g_slice_free (BakingData, bd); } static void decorated_cb (Cake *cake, GAsyncResult *result, gpointer user_data) { GTask *task = user_data; GError *error = NULL; if (!cake_decorate_finish (cake, result, &error)) { g_object_unref (cake); g_task_return_error (task, error); g_object_unref (task); return; } // baking_data_free() will drop its ref on the cake, so we have to // take another here to give to the caller. g_task_return_pointer (task, g_object_ref (cake), g_object_unref); g_object_unref (task); } static gboolean decorator_ready (gpointer user_data) { GTask *task = user_data; BakingData *bd = g_task_get_task_data (task); cake_decorate_async (bd->cake, bd->frosting, bd->message, g_task_get_cancellable (task), decorated_cb, task); return G_SOURCE_REMOVE; } static void baked_cb (Cake *cake, gpointer user_data) { GTask *task = user_data; BakingData *bd = g_task_get_task_data (task); GError *error = NULL; if (cake == NULL) { g_task_return_new_error (task, BAKER_ERROR, BAKER_ERROR_NO_FLOUR, "Go to the supermarket"); g_object_unref (task); return; } bd->cake = cake; // Bail out now if the user has already cancelled if (g_task_return_error_if_cancelled (task)) { g_object_unref (task); return; } if (cake_decorator_available (cake)) decorator_ready (task); else { GSource *source; source = cake_decorator_wait_source_new (cake); // Attach @source to @task’s GMainContext and have it call // decorator_ready() when it is ready. g_task_attach_source (task, source, decorator_ready); g_source_unref (source); } } void baker_bake_cake_async (Baker *self, guint radius, CakeFlavor flavor, CakeFrostingType frosting, const char *message, gint priority, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GTask *task; BakingData *bd; task = g_task_new (self, cancellable, callback, user_data); g_task_set_priority (task, priority); bd = g_slice_new0 (BakingData); bd->frosting = frosting; bd->message = g_strdup (message); g_task_set_task_data (task, bd, (GDestroyNotify) baking_data_free); _baker_begin_cake (self, radius, flavor, cancellable, baked_cb, task); } Cake * baker_bake_cake_finish (Baker *self, GAsyncResult *result, GError **error) { g_return_val_if_fail (g_task_is_valid (result, self), NULL); return g_task_propagate_pointer (G_TASK (result), error); }
Asynchronous operations from synchronous ones
You can use taskRunInThread
to turn a synchronous
operation into an asynchronous one, by running it in a thread.
When it completes, the result will be dispatched to the thread-default main
context (see mainContextPushThreadDefault
) where the GTask
was created.
Running a task in a thread:
c code
typedef struct { guint radius; CakeFlavor flavor; CakeFrostingType frosting; char *message; } CakeData; static void cake_data_free (CakeData *cake_data) { g_free (cake_data->message); g_slice_free (CakeData, cake_data); } static void bake_cake_thread (GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable) { Baker *self = source_object; CakeData *cake_data = task_data; Cake *cake; GError *error = NULL; cake = bake_cake (baker, cake_data->radius, cake_data->flavor, cake_data->frosting, cake_data->message, cancellable, &error); if (cake) g_task_return_pointer (task, cake, g_object_unref); else g_task_return_error (task, error); } void baker_bake_cake_async (Baker *self, guint radius, CakeFlavor flavor, CakeFrostingType frosting, const char *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { CakeData *cake_data; GTask *task; cake_data = g_slice_new (CakeData); cake_data->radius = radius; cake_data->flavor = flavor; cake_data->frosting = frosting; cake_data->message = g_strdup (message); task = g_task_new (self, cancellable, callback, user_data); g_task_set_task_data (task, cake_data, (GDestroyNotify) cake_data_free); g_task_run_in_thread (task, bake_cake_thread); g_object_unref (task); } Cake * baker_bake_cake_finish (Baker *self, GAsyncResult *result, GError **error) { g_return_val_if_fail (g_task_is_valid (result, self), NULL); return g_task_propagate_pointer (G_TASK (result), error); }
Adding cancellability to uncancellable tasks
Finally, taskRunInThread
and
taskRunInThreadSync
can be used to turn an uncancellable
operation into a cancellable one. If you call
taskSetReturnOnCancel
, passing TRUE
, then if the task’s
Cancellable
is cancelled, it will return control back to the
caller immediately, while allowing the task thread to continue running in the
background (and simply discarding its result when it finally does finish).
Provided that the task thread is careful about how it uses
locks and other externally-visible resources, this allows you
to make ‘GLib-friendly’ asynchronous and cancellable
synchronous variants of blocking APIs.
Cancelling a task:
c code
static void bake_cake_thread (GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable) { Baker *self = source_object; CakeData *cake_data = task_data; Cake *cake; GError *error = NULL; cake = bake_cake (baker, cake_data->radius, cake_data->flavor, cake_data->frosting, cake_data->message, &error); if (error) { g_task_return_error (task, error); return; } // If the task has already been cancelled, then we don’t want to add // the cake to the cake cache. Likewise, we don’t want to have the // task get cancelled in the middle of updating the cache. // g_task_set_return_on_cancel() will return %TRUE here if it managed // to disable return-on-cancel, or %FALSE if the task was cancelled // before it could. if (g_task_set_return_on_cancel (task, FALSE)) { // If the caller cancels at this point, their // GAsyncReadyCallback won’t be invoked until we return, // so we don’t have to worry that this code will run at // the same time as that code does. But if there were // other functions that might look at the cake cache, // then we’d probably need a GMutex here as well. baker_add_cake_to_cache (baker, cake); g_task_return_pointer (task, cake, g_object_unref); } } void baker_bake_cake_async (Baker *self, guint radius, CakeFlavor flavor, CakeFrostingType frosting, const char *message, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { CakeData *cake_data; GTask *task; cake_data = g_slice_new (CakeData); ... task = g_task_new (self, cancellable, callback, user_data); g_task_set_task_data (task, cake_data, (GDestroyNotify) cake_data_free); g_task_set_return_on_cancel (task, TRUE); g_task_run_in_thread (task, bake_cake_thread); } Cake * baker_bake_cake_sync (Baker *self, guint radius, CakeFlavor flavor, CakeFrostingType frosting, const char *message, GCancellable *cancellable, GError **error) { CakeData *cake_data; GTask *task; Cake *cake; cake_data = g_slice_new (CakeData); ... task = g_task_new (self, cancellable, NULL, NULL); g_task_set_task_data (task, cake_data, (GDestroyNotify) cake_data_free); g_task_set_return_on_cancel (task, TRUE); g_task_run_in_thread_sync (task, bake_cake_thread); cake = g_task_propagate_pointer (task, error); g_object_unref (task); return cake; }
Porting from SimpleAsyncResult
GTask
’s API attempts to be simpler than SimpleAsyncResult
’s
in several ways:
- You can save task-specific data with
taskSetTaskData
, and retrieve it later withtaskGetTaskData
. This replaces the abuse ofSimpleAsyncResult
.set_op_res_gpointer
() for the same purpose withSimpleAsyncResult
. - In addition to the task data,
GTask
also keeps track of the priority,Cancellable
, andMainContext
associated with the task, so tasks that consist of a chain of simpler asynchronous operations will have easy access to those values when starting each sub-task. taskReturnErrorIfCancelled
provides simplified handling for cancellation. In addition, cancellation overrides any otherGTask
return value by default, likeSimpleAsyncResult
does whensimpleAsyncResultSetCheckCancellable
is called. (You can usetaskSetCheckCancellable
to turn off that behavior.) On the other hand,taskRunInThread
guarantees that it will always run yourtask_func
, even if the task’sCancellable
is already cancelled before the task gets a chance to run; you can start yourtask_func
with ataskReturnErrorIfCancelled
check if you need the old behavior.- The ‘return’ methods (eg,
taskReturnPointer
) automatically cause the task to be ‘completed’ as well, and there is no need to worry about the ‘complete’ vs ‘complete in idle’ distinction. (GTask
automatically figures out whether the task’s callback can be invoked directly, or if it needs to be sent to anotherMainContext
, or delayed until the next iteration of the currentMainContext
.) - The ‘finish’ functions for
GTask
based operations are generally much simpler thanSimpleAsyncResult
ones, normally consisting of only a single call totaskPropagatePointer
or the like. SincetaskPropagatePointer
‘steals’ the return value from theGTask
, it is not necessary to juggle pointers around to prevent it from being freed twice. - With
SimpleAsyncResult
, it was common to callsimpleAsyncResultPropagateError
from the_finish()
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 appropriateg_task_propagate_
function. Note that wrapper methods can now useasyncResultLegacyPropagateError
to do old-styleSimpleAsyncResult
error-returning behavior, andasyncResultIsTagged
to check if a result is tagged as having come from the_async()
wrapper function (for ‘short-circuit’ results, such as when passing0
toinputStreamReadAsync
).
Thread-safety considerations
Due to some infelicities in the API design, there is a
thread-safety concern that users of GTask
have to be aware of:
If the main
thread drops its last reference to the source object
or the task data before the task is finalized, then the finalizers
of these objects may be called on the worker thread.
This is a problem if the finalizers use non-threadsafe API, and can lead to hard-to-debug crashes. Possible workarounds include:
- Clear task data in a signal handler for
notify::completed
- Keep iterating a main context in the main thread and defer dropping the reference to the source object to that main context when the task is finalized
Synopsis
- newtype Task = Task (ManagedPtr Task)
- class (GObject o, IsDescendantOf Task o) => IsTask o
- toTask :: (MonadIO m, IsTask o) => o -> m Task
- taskGetCancellable :: (HasCallStack, MonadIO m, IsTask a) => a -> m (Maybe Cancellable)
- taskGetCheckCancellable :: (HasCallStack, MonadIO m, IsTask a) => a -> m Bool
- taskGetCompleted :: (HasCallStack, MonadIO m, IsTask a) => a -> m Bool
- taskGetContext :: (HasCallStack, MonadIO m, IsTask a) => a -> m MainContext
- taskGetName :: (HasCallStack, MonadIO m, IsTask a) => a -> m (Maybe Text)
- taskGetPriority :: (HasCallStack, MonadIO m, IsTask a) => a -> m Int32
- taskGetReturnOnCancel :: (HasCallStack, MonadIO m, IsTask a) => a -> m Bool
- taskGetSourceObject :: (HasCallStack, MonadIO m, IsTask a) => a -> m (Maybe Object)
- taskGetSourceTag :: (HasCallStack, MonadIO m, IsTask a) => a -> m (Ptr ())
- taskGetTaskData :: (HasCallStack, MonadIO m, IsTask a) => a -> m (Ptr ())
- taskHadError :: (HasCallStack, MonadIO m, IsTask a) => a -> m Bool
- taskIsValid :: (HasCallStack, MonadIO m, IsAsyncResult a, IsObject b) => a -> Maybe b -> m Bool
- taskNew :: (HasCallStack, MonadIO m, IsObject a, IsCancellable b) => Maybe a -> Maybe b -> Maybe AsyncReadyCallback -> m Task
- taskPropagateBoolean :: (HasCallStack, MonadIO m, IsTask a) => a -> m ()
- taskPropagateInt :: (HasCallStack, MonadIO m, IsTask a) => a -> m Int64
- taskPropagatePointer :: (HasCallStack, MonadIO m, IsTask a) => a -> m (Ptr ())
- taskPropagateValue :: (HasCallStack, MonadIO m, IsTask a) => a -> m GValue
- taskReportError :: (HasCallStack, MonadIO m, IsObject a) => Maybe a -> Maybe AsyncReadyCallback -> Ptr () -> GError -> m ()
- taskReturnBoolean :: (HasCallStack, MonadIO m, IsTask a) => a -> Bool -> m ()
- taskReturnError :: (HasCallStack, MonadIO m, IsTask a) => a -> GError -> m ()
- taskReturnErrorIfCancelled :: (HasCallStack, MonadIO m, IsTask a) => a -> m Bool
- taskReturnInt :: (HasCallStack, MonadIO m, IsTask a) => a -> Int64 -> m ()
- taskReturnNewErrorLiteral :: (HasCallStack, MonadIO m, IsTask a) => a -> Word32 -> Int32 -> Text -> m ()
- taskReturnPointer :: (HasCallStack, MonadIO m, IsTask a) => a -> Ptr () -> Maybe DestroyNotify -> m ()
- taskReturnValue :: (HasCallStack, MonadIO m, IsTask a) => a -> Maybe GValue -> m ()
- taskRunInThread :: (HasCallStack, MonadIO m, IsTask a) => a -> TaskThreadFunc -> m ()
- taskRunInThreadSync :: (HasCallStack, MonadIO m, IsTask a) => a -> TaskThreadFunc -> m ()
- taskSetCheckCancellable :: (HasCallStack, MonadIO m, IsTask a) => a -> Bool -> m ()
- taskSetName :: (HasCallStack, MonadIO m, IsTask a) => a -> Maybe Text -> m ()
- taskSetPriority :: (HasCallStack, MonadIO m, IsTask a) => a -> Int32 -> m ()
- taskSetReturnOnCancel :: (HasCallStack, MonadIO m, IsTask a) => a -> Bool -> m Bool
- taskSetSourceTag :: (HasCallStack, MonadIO m, IsTask a) => a -> Ptr () -> m ()
- taskSetStaticName :: (HasCallStack, MonadIO m, IsTask a) => a -> Maybe Text -> m ()
- taskSetTaskData :: (HasCallStack, MonadIO m, IsTask a) => a -> Ptr () -> Maybe DestroyNotify -> m ()
- getTaskCompleted :: (MonadIO m, IsTask o) => o -> m Bool
Exported types
Memory-managed wrapper type.
Instances
Eq Task Source # | |
GObject Task Source # | |
Defined in GI.Gio.Objects.Task | |
ManagedPtrNewtype Task Source # | |
Defined in GI.Gio.Objects.Task toManagedPtr :: Task -> ManagedPtr Task # | |
TypedObject Task Source # | |
Defined in GI.Gio.Objects.Task | |
HasParentTypes Task Source # | |
Defined in GI.Gio.Objects.Task | |
IsGValue (Maybe Task) Source # | Convert |
Defined in GI.Gio.Objects.Task | |
type ParentTypes Task Source # | |
Defined in GI.Gio.Objects.Task |
class (GObject o, IsDescendantOf Task o) => IsTask o Source #
Instances
(GObject o, IsDescendantOf Task o) => IsTask o Source # | |
Defined in GI.Gio.Objects.Task |
Methods
Click to display all available methods, including inherited ones
Methods
bindProperty, bindPropertyFull, forceFloating, freezeNotify, getv, hadError, isFloating, isTagged, legacyPropagateError, notify, notifyByPspec, propagateBoolean, propagateInt, propagatePointer, propagateValue, ref, refSink, returnBoolean, returnError, returnErrorIfCancelled, returnInt, returnNewErrorLiteral, returnPointer, returnValue, runDispose, runInThread, runInThreadSync, stealData, stealQdata, thawNotify, unref, watchClosure.
Getters
getCancellable, getCheckCancellable, getCompleted, getContext, getData, getName, getPriority, getProperty, getQdata, getReturnOnCancel, getSourceObject, getSourceTag, getTaskData, getUserData.
Setters
setCheckCancellable, setData, setDataFull, setName, setPriority, setProperty, setReturnOnCancel, setSourceTag, setStaticName, setTaskData.
getCancellable
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> m (Maybe Cancellable) | Returns: |
Gets task
's Cancellable
Since: 2.36
getCheckCancellable
taskGetCheckCancellable Source #
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> m Bool |
Gets task
's check-cancellable flag. See
taskSetCheckCancellable
for more details.
Since: 2.36
getCompleted
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> m Bool |
Gets the value of Task:completed. This changes from False
to True
after
the task’s callback is invoked, and will return False
if called from inside
the callback.
Since: 2.44
getContext
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> m MainContext | Returns: |
Gets the MainContext
that task
will return its result in (that
is, the context that was the
[thread-default main context][g-main-context-push-thread-default]
at the point when task
was created).
This will always return a non-Nothing
value, even if the task's
context is the default MainContext
.
Since: 2.36
getName
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> m (Maybe Text) | Returns: |
Gets task
’s name. See taskSetName
.
Since: 2.60
getPriority
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> m Int32 | Returns: |
Gets task
's priority
Since: 2.36
getReturnOnCancel
taskGetReturnOnCancel Source #
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> m Bool |
Gets task
's return-on-cancel flag. See
taskSetReturnOnCancel
for more details.
Since: 2.36
getSourceObject
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> m (Maybe Object) | Returns: |
Gets the source object from task
. Like
asyncResultGetSourceObject
, but does not ref the object.
Since: 2.36
getSourceTag
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> m (Ptr ()) | Returns: |
Gets task
's source tag. See taskSetSourceTag
.
Since: 2.36
getTaskData
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> m (Ptr ()) | Returns: |
Gets task
's task_data
.
Since: 2.36
hadError
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> m Bool | Returns: |
Tests if task
resulted in an error.
Since: 2.36
isValid
:: (HasCallStack, MonadIO m, IsAsyncResult a, IsObject b) | |
=> a |
|
-> Maybe b |
|
-> m Bool | Returns: |
new
:: (HasCallStack, MonadIO m, IsObject a, IsCancellable b) | |
=> Maybe a | |
-> Maybe b |
|
-> Maybe AsyncReadyCallback |
|
-> m Task | Returns: a |
Creates a Task
acting on sourceObject
, which will eventually be
used to invoke callback
in the current
[thread-default main context][g-main-context-push-thread-default].
Call this in the "start" method of your asynchronous method, and
pass the Task
around throughout the asynchronous operation. You
can use taskSetTaskData
to attach task-specific data to the
object, which you can retrieve later via taskGetTaskData
.
By default, if cancellable
is cancelled, then the return value of
the task will always be IOErrorEnumCancelled
, even if the task had
already completed before the cancellation. This allows for
simplified handling in cases where cancellation may imply that
other objects that the task depends on have been destroyed. If you
do not want this behavior, you can use
taskSetCheckCancellable
to change it.
Since: 2.36
propagateBoolean
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> m () | (Can throw |
propagateInt
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> m Int64 | Returns: the task result, or -1 on error (Can throw |
Gets the result of task
as an integer (gssize
).
If the task resulted in an error, or was cancelled, then this will
instead return -1 and set error
.
Since this method transfers ownership of the return value (or error) to the caller, you may only call it once.
Since: 2.36
propagatePointer
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> m (Ptr ()) | Returns: the task result, or |
Gets the result of task
as a pointer, and transfers ownership
of that value to the caller.
If the task resulted in an error, or was cancelled, then this will
instead return Nothing
and set error
.
Since this method transfers ownership of the return value (or error) to the caller, you may only call it once.
Since: 2.36
propagateValue
Gets the result of task
as a Value
, and transfers ownership of
that value to the caller. As with taskReturnValue
, this is
a generic low-level method; taskPropagatePointer
and the like
will usually be more useful for C code.
If the task resulted in an error, or was cancelled, then this will
instead set error
and return False
.
Since this method transfers ownership of the return value (or error) to the caller, you may only call it once.
Since: 2.64
reportError
:: (HasCallStack, MonadIO m, IsObject a) | |
=> Maybe a | |
-> Maybe AsyncReadyCallback |
|
-> Ptr () |
|
-> GError |
|
-> m () |
Creates a Task
and then immediately calls taskReturnError
on it. Use this in the wrapper function of an asynchronous method
when you want to avoid even calling the virtual method. You can
then use asyncResultIsTagged
in the finish method wrapper to
check if the result there is tagged as having been created by the
wrapper method, and deal with it appropriately if so.
See also g_task_report_new_error()
.
Since: 2.36
returnBoolean
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> Bool |
|
-> m () |
Sets task
's result to result
and completes the task (see
taskReturnPointer
for more discussion of exactly what this
means).
Since: 2.36
returnError
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> GError |
|
-> m () |
Sets task
's result to error
(which task
assumes ownership of)
and completes the task (see taskReturnPointer
for more
discussion of exactly what this means).
Note that since the task takes ownership of error
, and since the
task may be completed before returning from taskReturnError
,
you cannot assume that error
is still valid after calling this.
Call errorCopy
on the error if you need to keep a local copy
as well.
See also Task
.return_new_error
(),
taskReturnNewErrorLiteral
.
Since: 2.36
returnErrorIfCancelled
taskReturnErrorIfCancelled Source #
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> m Bool |
Checks if task
's Cancellable
has been cancelled, and if so, sets
task
's error accordingly and completes the task (see
taskReturnPointer
for more discussion of exactly what this
means).
Since: 2.36
returnInt
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> Int64 |
|
-> m () |
Sets task
's result to result
and completes the task (see
taskReturnPointer
for more discussion of exactly what this
means).
Since: 2.36
returnNewErrorLiteral
taskReturnNewErrorLiteral Source #
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> Word32 |
|
-> Int32 |
|
-> Text |
|
-> m () |
Sets task
’s result to a new [typegLib
.Error] created from domain
, code
,
message
and completes the task.
See taskReturnPointer
for more discussion of exactly what
‘completing the task’ means.
See also Task
.return_new_error
().
Since: 2.80
returnPointer
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> Ptr () |
|
-> Maybe DestroyNotify |
|
-> m () |
Sets task
's result to result
and completes the task. If result
is not Nothing
, then resultDestroy
will be used to free result
if
the caller does not take ownership of it with
taskPropagatePointer
.
"Completes the task" means that for an ordinary asynchronous task
it will either invoke the task's callback, or else queue that
callback to be invoked in the proper MainContext
, or in the next
iteration of the current MainContext
. For a task run via
taskRunInThread
or taskRunInThreadSync
, calling this
method will save result
to be returned to the caller later, but
the task will not actually be completed until the TaskThreadFunc
exits.
Note that since the task may be completed before returning from
taskReturnPointer
, you cannot assume that result
is still
valid after calling this, unless you are still holding another
reference on it.
Since: 2.36
returnValue
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> Maybe GValue |
|
-> m () |
Sets task
's result to result
(by copying it) and completes the task.
If result
is Nothing
then a Value
of type G_TYPE_POINTER
with a value of Nothing
will be used for the result.
This is a very generic low-level method intended primarily for use
by language bindings; for C code, taskReturnPointer
and the
like will normally be much easier to use.
Since: 2.64
runInThread
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> TaskThreadFunc |
|
-> m () |
Runs taskFunc
in another thread. When taskFunc
returns, task
's
AsyncReadyCallback
will be invoked in task
's MainContext
.
This takes a ref on task
until the task completes.
See TaskThreadFunc
for more details about how taskFunc
is handled.
Although GLib currently rate-limits the tasks queued via
taskRunInThread
, you should not assume that it will always
do this. If you have a very large number of tasks to run (several tens of
tasks), but don't want them to all run at once, you should only queue a
limited number of them (around ten) at a time.
Be aware that if your task depends on other tasks to complete, use of this
function could lead to a livelock if the other tasks also use this function
and enough of them (around 10) execute in a dependency chain, as that will
exhaust the thread pool. If this situation is possible, consider using a
separate worker thread or thread pool explicitly, rather than using
taskRunInThread
.
Since: 2.36
runInThreadSync
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> TaskThreadFunc |
|
-> m () |
Runs taskFunc
in another thread, and waits for it to return or be
cancelled. You can use taskPropagatePointer
, etc, afterward
to get the result of taskFunc
.
See TaskThreadFunc
for more details about how taskFunc
is handled.
Normally this is used with tasks created with a Nothing
callback
, but note that even if the task does
have a callback, it will not be invoked when taskFunc
returns.
Task:completed will be set to True
just before this function returns.
Although GLib currently rate-limits the tasks queued via
taskRunInThreadSync
, you should not assume that it will
always do this. If you have a very large number of tasks to run,
but don't want them to all run at once, you should only queue a
limited number of them at a time.
Since: 2.36
setCheckCancellable
taskSetCheckCancellable Source #
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> Bool |
|
-> m () |
Sets or clears task
's check-cancellable flag. If this is True
(the default), then taskPropagatePointer
, etc, and
taskHadError
will check the task's Cancellable
first, and
if it has been cancelled, then they will consider the task to have
returned an "Operation was cancelled" error
(IOErrorEnumCancelled
), regardless of any other error or return
value the task may have had.
If checkCancellable
is False
, then the Task
will not check the
cancellable itself, and it is up to task
's owner to do this (eg,
via taskReturnErrorIfCancelled
).
If you are using taskSetReturnOnCancel
as well, then
you must leave check-cancellable set True
.
Since: 2.36
setName
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> Maybe Text |
|
-> m () |
Sets task
’s name, used in debugging and profiling. The name defaults to
Nothing
.
The task name should describe in a human readable way what the task does.
For example, ‘Open file’ or ‘Connect to network host’. It is used to set the
name of the Source
used for idle completion of the task.
This function may only be called before the task
is first used in a thread
other than the one it was constructed in. It is called automatically by
taskSetSourceTag
if not called already.
Since: 2.60
setPriority
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> Int32 |
|
-> m () |
Sets task
's priority. If you do not call this, it will default to
PRIORITY_DEFAULT
.
This will affect the priority of GSources
created with
g_task_attach_source()
and the scheduling of tasks run in threads,
and can also be explicitly retrieved later via
taskGetPriority
.
Since: 2.36
setReturnOnCancel
taskSetReturnOnCancel Source #
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> Bool |
|
-> m Bool | Returns: |
Sets or clears task
's return-on-cancel flag. This is only
meaningful for tasks run via taskRunInThread
or
taskRunInThreadSync
.
If returnOnCancel
is True
, then cancelling task
's
Cancellable
will immediately cause it to return, as though the
task's TaskThreadFunc
had called
taskReturnErrorIfCancelled
and then returned.
This allows you to create a cancellable wrapper around an
uninterruptible function. The TaskThreadFunc
just needs to be
careful that it does not modify any externally-visible state after
it has been cancelled. To do that, the thread should call
taskSetReturnOnCancel
again to (atomically) set
return-on-cancel False
before making externally-visible changes;
if the task gets cancelled before the return-on-cancel flag could
be changed, taskSetReturnOnCancel
will indicate this by
returning False
.
You can disable and re-enable this flag multiple times if you wish.
If the task's Cancellable
is cancelled while return-on-cancel is
False
, then calling taskSetReturnOnCancel
to set it True
again will cause the task to be cancelled at that point.
If the task's Cancellable
is already cancelled before you call
taskRunInThread
/taskRunInThreadSync
, then the
TaskThreadFunc
will still be run (for consistency), but the task
will also be completed right away.
Since: 2.36
setSourceTag
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> Ptr () |
|
-> m () |
Sets task
's source tag.
You can use this to tag a task return
value with a particular pointer (usually a pointer to the function
doing the tagging) and then later check it using
taskGetSourceTag
(or asyncResultIsTagged
) in the
task's "finish" function, to figure out if the response came from a
particular place.
A macro wrapper around this function will automatically set the
task’s name to the string form of sourceTag
if it’s not already
set, for convenience.
Since: 2.36
setStaticName
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> Maybe Text |
|
-> m () |
Sets task
’s name, used in debugging and profiling.
This is a variant of taskSetName
that avoids copying name
.
Since: 2.76
setTaskData
:: (HasCallStack, MonadIO m, IsTask a) | |
=> a |
|
-> Ptr () |
|
-> Maybe DestroyNotify |
|
-> m () |
Sets task
's task data (freeing the existing task data, if any).
Since: 2.36
Properties
completed
Whether the task has completed, meaning its callback (if set) has been invoked.
This can only happen after taskReturnPointer
,
taskReturnError
or one of the other return functions have been called
on the task. However, it is not guaranteed to happen immediately after
those functions are called, as the task’s callback may need to be scheduled
to run in a different thread.
That means it is not safe to use this property to track whether a
return function has been called on the Task
. Callers must do that
tracking themselves, typically by linking the lifetime of the Task
to the
control flow of their code.
This property is guaranteed to change from False
to True
exactly once.
The Object::notify signal for this change is emitted in the same main context as the task’s callback, immediately after that callback is invoked.
Since: 2.44
getTaskCompleted :: (MonadIO m, IsTask o) => o -> m Bool Source #
Get the value of the “completed
” property.
When overloading is enabled, this is equivalent to
get
task #completed