GSimpleAsyncResult

As of GLib 2.46, gio.simple_async_result.SimpleAsyncResult is deprecated in favor of gio.task.Task, which provides a simpler API.

gio.simple_async_result.SimpleAsyncResult implements gio.async_result.AsyncResult.

gio.simple_async_result.SimpleAsyncResult handles gio.types.AsyncReadyCallbacks, error reporting, operation cancellation and the final state of an operation, completely transparent to the application. Results can be returned as a pointer e.g. for functions that return data that is collected asynchronously, a boolean value for checking the success or failure of an operation, or a gssize for operations which return the number of bytes modified by the operation; all of the simple return cases are covered.

Most of the time, an application will not need to know of the details of this API; it is handled transparently, and any necessary operations are handled by gio.async_result.AsyncResult’s interface. However, if implementing a new GIO module, for writing language bindings, or for complex applications that need better control of how asynchronous operations are completed, it is important to understand this functionality.

gio.simple_async_result.SimpleAsyncResults are tagged with the calling function to ensure that asynchronous functions and their finishing functions are used together correctly.

To create a new gio.simple_async_result.SimpleAsyncResult, call gio.simple_async_result.SimpleAsyncResult.new_. If the result needs to be created for a glib.error.ErrorG, use gio.simple_async_result.SimpleAsyncResult.newFromError or gio.simple_async_result.SimpleAsyncResult.newTakeError. If a glib.error.ErrorG is not available (e.g. the asynchronous operation doesn’t take a glib.error.ErrorG argument), but the result still needs to be created for an error condition, use gio.simple_async_result.SimpleAsyncResult.newError (or gio.simple_async_result.SimpleAsyncResult.setErrorVa if your application or binding requires passing a variable argument list directly), and the error can then be propagated through the use of gio.simple_async_result.SimpleAsyncResult.propagateError.

An asynchronous operation can be made to ignore a cancellation event by calling gio.simple_async_result.SimpleAsyncResult.setHandleCancellation with a gio.simple_async_result.SimpleAsyncResult for the operation and FALSE. This is useful for operations that are dangerous to cancel, such as close (which would cause a leak if cancelled before being run).

gio.simple_async_result.SimpleAsyncResult can integrate into GLib’s event loop, glib.main_loop.MainLoop, or it can use glib.thread.Threads. gio.simple_async_result.SimpleAsyncResult.complete will finish an I/O task directly from the point where it is called. gio.simple_async_result.SimpleAsyncResult.completeInIdle will finish it from an idle handler in the thread-default main context (see glib.main_context.MainContext.pushThreadDefault) where the gio.simple_async_result.SimpleAsyncResult was created. gio.simple_async_result.SimpleAsyncResult.runInThread will run the job in a separate thread and then use gio.simple_async_result.SimpleAsyncResult.completeInIdle to deliver the result.

To set the results of an asynchronous function, gio.simple_async_result.SimpleAsyncResult.setOpResGpointer, gio.simple_async_result.SimpleAsyncResult.setOpResGboolean, and gio.simple_async_result.SimpleAsyncResult.setOpResGssize

are provided, setting the operation's result to a [xlib.types.void*], glib.types.SOURCE_REMOVE, or gssize, respectively.

Likewise, to get the result of an asynchronous function, gio.simple_async_result.SimpleAsyncResult.getOpResGpointer, gio.simple_async_result.SimpleAsyncResult.getOpResGboolean, and gio.simple_async_result.SimpleAsyncResult.getOpResGssize are provided, getting the operation’s result as a [xlib.types.void*], glib.types.SOURCE_REMOVE, and gssize, respectively.

For the details of the requirements implementations must respect, see gio.async_result.AsyncResult. A typical implementation of an asynchronous operation using gio.simple_async_result.SimpleAsyncResult looks something like this:

1 static void
2 baked_cb (Cake    *cake,
3           gpointer user_data)
4 {
5   // In this example, this callback is not given a reference to the cake,
6   // so the GSimpleAsyncResult has to take a reference to it.
7   GSimpleAsyncResult *result = user_data;
8 
9   if (cake == NULL)
10     g_simple_async_result_set_error (result,
11                                      BAKER_ERRORS,
12                                      BAKER_ERROR_NO_FLOUR,
13                                      "Go to the supermarket");
14   else
15     g_simple_async_result_set_op_res_gpointer (result,
16                                                g_object_ref (cake),
17                                                g_object_unref);
18 
19 
20   // In this example, we assume that baked_cb is called as a callback from
21   // the mainloop, so it's safe to complete the operation synchronously here.
22   // If, however, _baker_prepare_cake () might call its callback without
23   // first returning to the mainloop — inadvisable, but some APIs do so —
24   // we would need to use g_simple_async_result_complete_in_idle().
25   g_simple_async_result_complete (result);
26   g_object_unref (result);
27 }
28 
29 void
30 baker_bake_cake_async (Baker              *self,
31                        guint               radius,
32                        GAsyncReadyCallback callback,
33                        gpointer            user_data)
34 {
35   GSimpleAsyncResult *simple;
36   Cake               *cake;
37 
38   if (radius < 3)
39     {
40       g_simple_async_report_error_in_idle (G_OBJECT (self),
41                                            callback,
42                                            user_data,
43                                            BAKER_ERRORS,
44                                            BAKER_ERROR_TOO_SMALL,
45                                            "%ucm radius cakes are silly",
46                                            radius);
47       return;
48     }
49 
50   simple = g_simple_async_result_new (G_OBJECT (self),
51                                       callback,
52                                       user_data,
53                                       baker_bake_cake_async);
54   cake = _baker_get_cached_cake (self, radius);
55 
56   if (cake != NULL)
57     {
58       g_simple_async_result_set_op_res_gpointer (simple,
59                                                  g_object_ref (cake),
60                                                  g_object_unref);
61       g_simple_async_result_complete_in_idle (simple);
62       g_object_unref (simple);
63       // Drop the reference returned by _baker_get_cached_cake();
64       // the GSimpleAsyncResult has taken its own reference.
65       g_object_unref (cake);
66       return;
67     }
68 
69   _baker_prepare_cake (self, radius, baked_cb, simple);
70 }
71 
72 Cake *
73 baker_bake_cake_finish (Baker        *self,
74                         GAsyncResult *result,
75                         GError      **error)
76 {
77   GSimpleAsyncResult *simple;
78   Cake               *cake;
79 
80   g_return_val_if_fail (g_simple_async_result_is_valid (result,
81                                                         G_OBJECT (self),
82                                                         baker_bake_cake_async),
83                         NULL);
84 
85   simple = (GSimpleAsyncResult *) result;
86 
87   if (g_simple_async_result_propagate_error (simple, error))
88     return NULL;
89 
90   cake = CAKE (g_simple_async_result_get_op_res_gpointer (simple));
91   return g_object_ref (cake);
92 }
struct GSimpleAsyncResult