Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright (C) 2006-2007 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Author: Alexander Larsson <alexl@redhat.com>
21 : : */
22 : :
23 : : #include "config.h"
24 : : #include "gasyncresult.h"
25 : : #include "gsimpleasyncresult.h"
26 : : #include "glibintl.h"
27 : :
28 : :
29 : : /**
30 : : * GAsyncResult:
31 : : *
32 : : * `GAsyncResult` provides a base class for implementing asynchronous function results.
33 : : *
34 : : * Asynchronous operations are broken up into two separate operations
35 : : * which are chained together by a `GAsyncReadyCallback`. To begin
36 : : * an asynchronous operation, provide a `GAsyncReadyCallback` to the
37 : : * asynchronous function. This callback will be triggered when the
38 : : * operation has completed, and must be run in a later iteration of
39 : : * the thread-default main context (see
40 : : * [method@GLib.MainContext.push_thread_default]) from where the operation was
41 : : * initiated. It will be passed a `GAsyncResult` instance filled with the
42 : : * details of the operation's success or failure, the object the asynchronous
43 : : * function was started for and any error codes returned. The asynchronous
44 : : * callback function is then expected to call the corresponding `_finish()`
45 : : * function, passing the object the function was called for, the
46 : : * `GAsyncResult` instance, and (optionally) an @error to grab any
47 : : * error conditions that may have occurred.
48 : : *
49 : : * The `_finish()` function for an operation takes the generic result
50 : : * (of type `GAsyncResult`) and returns the specific result that the
51 : : * operation in question yields (e.g. a [class@Gio.FileEnumerator] for a
52 : : * "enumerate children" operation). If the result or error status of the
53 : : * operation is not needed, there is no need to call the `_finish()`
54 : : * function; GIO will take care of cleaning up the result and error
55 : : * information after the `GAsyncReadyCallback` returns. You can pass
56 : : * `NULL` for the `GAsyncReadyCallback` if you don't need to take any
57 : : * action at all after the operation completes. Applications may also
58 : : * take a reference to the `GAsyncResult` and call `_finish()` later;
59 : : * however, the `_finish()` function may be called at most once.
60 : : *
61 : : * Example of a typical asynchronous operation flow:
62 : : *
63 : : * ```c
64 : : * void _theoretical_frobnitz_async (Theoretical *t,
65 : : * GCancellable *c,
66 : : * GAsyncReadyCallback cb,
67 : : * gpointer u);
68 : : *
69 : : * gboolean _theoretical_frobnitz_finish (Theoretical *t,
70 : : * GAsyncResult *res,
71 : : * GError **e);
72 : : *
73 : : * static void
74 : : * frobnitz_result_func (GObject *source_object,
75 : : * GAsyncResult *res,
76 : : * gpointer user_data)
77 : : * {
78 : : * gboolean success = FALSE;
79 : : *
80 : : * success = _theoretical_frobnitz_finish (source_object, res, NULL);
81 : : *
82 : : * if (success)
83 : : * g_printf ("Hurray!\n");
84 : : * else
85 : : * g_printf ("Uh oh!\n");
86 : : *
87 : : * ...
88 : : *
89 : : * }
90 : : *
91 : : * int main (int argc, void *argv[])
92 : : * {
93 : : * ...
94 : : *
95 : : * _theoretical_frobnitz_async (theoretical_data,
96 : : * NULL,
97 : : * frobnitz_result_func,
98 : : * NULL);
99 : : *
100 : : * ...
101 : : * }
102 : : * ```
103 : : *
104 : : * The callback for an asynchronous operation is called only once, and is
105 : : * always called, even in the case of a cancelled operation. On cancellation
106 : : * the result is a `G_IO_ERROR_CANCELLED` error.
107 : : *
108 : : * ## I/O Priority
109 : : *
110 : : * Many I/O-related asynchronous operations have a priority parameter,
111 : : * which is used in certain cases to determine the order in which
112 : : * operations are executed. They are not used to determine system-wide
113 : : * I/O scheduling. Priorities are integers, with lower numbers indicating
114 : : * higher priority. It is recommended to choose priorities between
115 : : * `G_PRIORITY_LOW` and `G_PRIORITY_HIGH`, with `G_PRIORITY_DEFAULT`
116 : : * as a default.
117 : : */
118 : :
119 : : typedef GAsyncResultIface GAsyncResultInterface;
120 : 214317 : G_DEFINE_INTERFACE (GAsyncResult, g_async_result, G_TYPE_OBJECT)
121 : :
122 : : static void
123 : 163 : g_async_result_default_init (GAsyncResultInterface *iface)
124 : : {
125 : 163 : }
126 : :
127 : : /**
128 : : * g_async_result_get_user_data:
129 : : * @res: a [iface@Gio.AsyncResult].
130 : : *
131 : : * Gets the user data from a [iface@Gio.AsyncResult].
132 : : *
133 : : * Returns: (transfer full): the user data for @res.
134 : : **/
135 : : gpointer
136 : 47 : g_async_result_get_user_data (GAsyncResult *res)
137 : : {
138 : : GAsyncResultIface *iface;
139 : :
140 : 47 : g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
141 : :
142 : 47 : iface = G_ASYNC_RESULT_GET_IFACE (res);
143 : :
144 : 47 : return (* iface->get_user_data) (res);
145 : : }
146 : :
147 : : /**
148 : : * g_async_result_get_source_object:
149 : : * @res: a [iface@Gio.AsyncResult]
150 : : *
151 : : * Gets the source object from a [iface@Gio.AsyncResult].
152 : : *
153 : : * Returns: (transfer full) (nullable): a new reference to the source
154 : : * object for the @res, or `NULL` if there is none.
155 : : */
156 : : GObject *
157 : 462 : g_async_result_get_source_object (GAsyncResult *res)
158 : : {
159 : : GAsyncResultIface *iface;
160 : :
161 : 462 : g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL);
162 : :
163 : 462 : iface = G_ASYNC_RESULT_GET_IFACE (res);
164 : :
165 : 462 : return (* iface->get_source_object) (res);
166 : : }
167 : :
168 : : /**
169 : : * g_async_result_legacy_propagate_error:
170 : : * @res: a [iface@Gio.AsyncResult]
171 : : * @error: (out): a location to propagate the error to.
172 : : *
173 : : * If @res is a [class@Gio.SimpleAsyncResult], this is equivalent to
174 : : * [method@Gio.SimpleAsyncResult.propagate_error]. Otherwise it returns
175 : : * `FALSE`.
176 : : *
177 : : * This can be used for legacy error handling in async `*_finish()`
178 : : * wrapper functions that traditionally handled [class@Gio.SimpleAsyncResult]
179 : : * error returns themselves rather than calling into the virtual method.
180 : : * This should not be used in new code; [iface@Gio.AsyncResult] errors that are
181 : : * set by virtual methods should also be extracted by virtual methods,
182 : : * to enable subclasses to chain up correctly.
183 : : *
184 : : * Returns: `TRUE` if @error is has been filled in with an error from
185 : : * @res, `FALSE` if not.
186 : : *
187 : : * Since: 2.34
188 : : **/
189 : : gboolean
190 : 33872 : g_async_result_legacy_propagate_error (GAsyncResult *res,
191 : : GError **error)
192 : : {
193 : : /* This doesn't use a vmethod, because it's only for code that used
194 : : * to use `GSimpleAsyncResult`. (But it's a `GAsyncResult` method so
195 : : * that callers don't need to worry about `GSimpleAsyncResult`
196 : : * deprecation warnings in the future.)
197 : : */
198 : :
199 : : G_GNUC_BEGIN_IGNORE_DEPRECATIONS
200 : 33872 : if (G_IS_SIMPLE_ASYNC_RESULT (res))
201 : : {
202 : 1 : return g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res),
203 : : error);
204 : : }
205 : : else
206 : 33871 : return FALSE;
207 : : G_GNUC_END_IGNORE_DEPRECATIONS
208 : : }
209 : :
210 : : /**
211 : : * g_async_result_is_tagged:
212 : : * @res: a [iface@Gio.AsyncResult]
213 : : * @source_tag: an application-defined tag
214 : : *
215 : : * Checks if @res has the given @source_tag (generally a function
216 : : * pointer indicating the function @res was created by).
217 : : *
218 : : * Returns: `TRUE` if @res has the indicated @source_tag, `FALSE` if
219 : : * not.
220 : : *
221 : : * Since: 2.34
222 : : **/
223 : : gboolean
224 : 31661 : g_async_result_is_tagged (GAsyncResult *res,
225 : : gpointer source_tag)
226 : : {
227 : : GAsyncResultIface *iface;
228 : :
229 : 31661 : g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
230 : :
231 : 31661 : iface = G_ASYNC_RESULT_GET_IFACE (res);
232 : :
233 : 31661 : if (!iface->is_tagged)
234 : 0 : return FALSE;
235 : :
236 : 31661 : return (* iface->is_tagged) (res, source_tag);
237 : : }
|