mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-05-18 03:31:57 +02:00
GSimpleAsyncResult: support reliable cancellation
Add a function g_simple_async_result_set_check_cancellable() to provide a GCancellable that is checked for being cancelled during the call to g_simple_async_result_propagate_error(). This gives asynchronous operation implementations an easy way to provide reliable cancellation of those operations -- even in the case that a positive result has occured and is pending dispatch at the time the operation is cancelled. https://bugzilla.gnome.org/show_bug.cgi?id=672013
This commit is contained in:
parent
53b1afba0e
commit
4804094472
@ -1211,6 +1211,7 @@ g_simple_async_result_new
|
|||||||
g_simple_async_result_new_error
|
g_simple_async_result_new_error
|
||||||
g_simple_async_result_new_from_error
|
g_simple_async_result_new_from_error
|
||||||
g_simple_async_result_new_take_error
|
g_simple_async_result_new_take_error
|
||||||
|
g_simple_async_result_set_check_cancellable
|
||||||
g_simple_async_result_set_op_res_gpointer
|
g_simple_async_result_set_op_res_gpointer
|
||||||
g_simple_async_result_get_op_res_gpointer
|
g_simple_async_result_get_op_res_gpointer
|
||||||
g_simple_async_result_set_op_res_gssize
|
g_simple_async_result_set_op_res_gssize
|
||||||
|
@ -596,6 +596,7 @@ g_simple_async_result_new
|
|||||||
g_simple_async_result_new_error
|
g_simple_async_result_new_error
|
||||||
g_simple_async_result_new_from_error
|
g_simple_async_result_new_from_error
|
||||||
g_simple_async_result_new_take_error
|
g_simple_async_result_new_take_error
|
||||||
|
g_simple_async_result_set_check_cancellable
|
||||||
g_simple_async_result_set_op_res_gpointer
|
g_simple_async_result_set_op_res_gpointer
|
||||||
g_simple_async_result_get_op_res_gpointer
|
g_simple_async_result_get_op_res_gpointer
|
||||||
g_simple_async_result_set_op_res_gssize
|
g_simple_async_result_set_op_res_gssize
|
||||||
|
@ -227,6 +227,7 @@ struct _GSimpleAsyncResult
|
|||||||
GError *error;
|
GError *error;
|
||||||
gboolean failed;
|
gboolean failed;
|
||||||
gboolean handle_cancellation;
|
gboolean handle_cancellation;
|
||||||
|
GCancellable *check_cancellable;
|
||||||
|
|
||||||
gpointer source_tag;
|
gpointer source_tag;
|
||||||
|
|
||||||
@ -268,6 +269,9 @@ g_simple_async_result_finalize (GObject *object)
|
|||||||
if (simple->source_object)
|
if (simple->source_object)
|
||||||
g_object_unref (simple->source_object);
|
g_object_unref (simple->source_object);
|
||||||
|
|
||||||
|
if (simple->check_cancellable)
|
||||||
|
g_object_unref (simple->check_cancellable);
|
||||||
|
|
||||||
g_main_context_unref (simple->context);
|
g_main_context_unref (simple->context);
|
||||||
|
|
||||||
clear_op_res (simple);
|
clear_op_res (simple);
|
||||||
@ -303,6 +307,15 @@ g_simple_async_result_init (GSimpleAsyncResult *simple)
|
|||||||
*
|
*
|
||||||
* Creates a #GSimpleAsyncResult.
|
* Creates a #GSimpleAsyncResult.
|
||||||
*
|
*
|
||||||
|
* The common convention is to create the #GSimpleAsyncResult in the
|
||||||
|
* function that starts the asynchronous operation and use that same
|
||||||
|
* function as the @source_tag.
|
||||||
|
*
|
||||||
|
* If your operation supports cancellation with #GCancellable (which it
|
||||||
|
* probably should) then you should provide the user's cancellable to
|
||||||
|
* g_simple_async_result_set_check_cancellable() immediately after
|
||||||
|
* this function returns.
|
||||||
|
*
|
||||||
* Returns: a #GSimpleAsyncResult.
|
* Returns: a #GSimpleAsyncResult.
|
||||||
**/
|
**/
|
||||||
GSimpleAsyncResult *
|
GSimpleAsyncResult *
|
||||||
@ -458,6 +471,9 @@ g_simple_async_result_async_result_iface_init (GAsyncResultIface *iface)
|
|||||||
*
|
*
|
||||||
* Sets whether to handle cancellation within the asynchronous operation.
|
* Sets whether to handle cancellation within the asynchronous operation.
|
||||||
*
|
*
|
||||||
|
* This function has nothing to do with
|
||||||
|
* g_simple_async_result_set_check_cancellable(). It only refers to the
|
||||||
|
* #GCancellable passed to g_simple_async_result_run_in_thread().
|
||||||
**/
|
**/
|
||||||
void
|
void
|
||||||
g_simple_async_result_set_handle_cancellation (GSimpleAsyncResult *simple,
|
g_simple_async_result_set_handle_cancellation (GSimpleAsyncResult *simple,
|
||||||
@ -490,6 +506,10 @@ g_simple_async_result_get_source_tag (GSimpleAsyncResult *simple)
|
|||||||
* Propagates an error from within the simple asynchronous result to
|
* Propagates an error from within the simple asynchronous result to
|
||||||
* a given destination.
|
* a given destination.
|
||||||
*
|
*
|
||||||
|
* If the #GCancellable given to a prior call to
|
||||||
|
* g_simple_async_result_set_check_cancellable() is cancelled then this
|
||||||
|
* function will return %TRUE with @dest set appropriately.
|
||||||
|
*
|
||||||
* Returns: %TRUE if the error was propagated to @dest. %FALSE otherwise.
|
* Returns: %TRUE if the error was propagated to @dest. %FALSE otherwise.
|
||||||
**/
|
**/
|
||||||
gboolean
|
gboolean
|
||||||
@ -498,6 +518,9 @@ g_simple_async_result_propagate_error (GSimpleAsyncResult *simple,
|
|||||||
{
|
{
|
||||||
g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple), FALSE);
|
g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple), FALSE);
|
||||||
|
|
||||||
|
if (g_cancellable_set_error_if_cancelled (simple->check_cancellable, dest))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
if (simple->failed)
|
if (simple->failed)
|
||||||
{
|
{
|
||||||
g_propagate_error (dest, simple->error);
|
g_propagate_error (dest, simple->error);
|
||||||
@ -1034,3 +1057,38 @@ g_simple_async_report_take_gerror_in_idle (GObject *object,
|
|||||||
g_simple_async_result_complete_in_idle (simple);
|
g_simple_async_result_complete_in_idle (simple);
|
||||||
g_object_unref (simple);
|
g_object_unref (simple);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_simple_async_result_set_check_cancellable:
|
||||||
|
* @simple: a #GSimpleAsyncResult
|
||||||
|
* @check_cancellable: a #GCancellable to check, or %NULL to unset
|
||||||
|
*
|
||||||
|
* Sets a #GCancellable to check before dispatching results.
|
||||||
|
*
|
||||||
|
* This function has one very specific purpose: the provided cancellable
|
||||||
|
* is checked at the time of g_simple_async_result_propagate_error() If
|
||||||
|
* it is cancelled, these functions will return an "Operation was
|
||||||
|
* cancelled" error (%G_IO_ERROR_CANCELLED).
|
||||||
|
*
|
||||||
|
* Implementors of cancellable asynchronous functions should use this in
|
||||||
|
* order to provide a guarantee to their callers that cancelling an
|
||||||
|
* async operation will reliably result in an error being returned for
|
||||||
|
* that operation (even if a positive result for the operation has
|
||||||
|
* already been sent as an idle to the main context to be dispatched).
|
||||||
|
*
|
||||||
|
* The checking described above is done regardless of any call to the
|
||||||
|
* unrelated g_simple_async_result_set_handle_cancellation() function.
|
||||||
|
*
|
||||||
|
* Since: 2.32
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
g_simple_async_result_set_check_cancellable (GSimpleAsyncResult *simple,
|
||||||
|
GCancellable *check_cancellable)
|
||||||
|
{
|
||||||
|
g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple));
|
||||||
|
g_return_if_fail (check_cancellable == NULL || G_IS_CANCELLABLE (check_cancellable));
|
||||||
|
|
||||||
|
g_clear_object (&simple->check_cancellable);
|
||||||
|
if (check_cancellable)
|
||||||
|
simple->check_cancellable = g_object_ref (check_cancellable);
|
||||||
|
}
|
||||||
|
@ -83,6 +83,8 @@ gboolean g_simple_async_result_get_op_res_gboolean (GSimpleAsyncResul
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void g_simple_async_result_set_check_cancellable (GSimpleAsyncResult *simple,
|
||||||
|
GCancellable *check_cancellable);
|
||||||
gpointer g_simple_async_result_get_source_tag (GSimpleAsyncResult *simple);
|
gpointer g_simple_async_result_get_source_tag (GSimpleAsyncResult *simple);
|
||||||
void g_simple_async_result_set_handle_cancellation (GSimpleAsyncResult *simple,
|
void g_simple_async_result_set_handle_cancellation (GSimpleAsyncResult *simple,
|
||||||
gboolean handle_cancellation);
|
gboolean handle_cancellation);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user