nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* GIO - GLib Input, Output and Streaming Library |
2 | * |
||
3 | * Copyright (C) 2009 Red Hat, Inc. |
||
4 | * |
||
5 | * This library is free software; you can redistribute it and/or |
||
6 | * modify it under the terms of the GNU Lesser General Public |
||
7 | * License as published by the Free Software Foundation; either |
||
8 | * version 2 of the License, or (at your option) any later version. |
||
9 | * |
||
10 | * This library is distributed in the hope that it will be useful, |
||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
13 | * Lesser General Public License for more details. |
||
14 | * |
||
15 | * You should have received a copy of the GNU Lesser General |
||
16 | * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. |
||
17 | * |
||
18 | * Author: Alexander Larsson <alexl@redhat.com> |
||
19 | */ |
||
20 | |||
21 | #include "config.h" |
||
22 | #include "gasyncinitable.h" |
||
23 | #include "gasyncresult.h" |
||
24 | #include "gsimpleasyncresult.h" |
||
25 | #include "gtask.h" |
||
26 | #include "glibintl.h" |
||
27 | |||
28 | |||
29 | /** |
||
30 | * SECTION:gasyncinitable |
||
31 | * @short_description: Asynchronously failable object initialization interface |
||
32 | * @include: gio/gio.h |
||
33 | * @see_also: #GInitable |
||
34 | * |
||
35 | * This is the asynchronous version of #GInitable; it behaves the same |
||
36 | * in all ways except that initialization is asynchronous. For more details |
||
37 | * see the descriptions on #GInitable. |
||
38 | * |
||
39 | * A class may implement both the #GInitable and #GAsyncInitable interfaces. |
||
40 | * |
||
41 | * Users of objects implementing this are not intended to use the interface |
||
42 | * method directly; instead it will be used automatically in various ways. |
||
43 | * For C applications you generally just call g_async_initable_new_async() |
||
44 | * directly, or indirectly via a foo_thing_new_async() wrapper. This will call |
||
45 | * g_async_initable_init_async() under the cover, calling back with %NULL and |
||
46 | * a set %GError on failure. |
||
47 | * |
||
48 | * A typical implementation might look something like this: |
||
49 | * |
||
50 | * |[<!-- language="C" --> |
||
51 | * enum { |
||
52 | * NOT_INITIALIZED, |
||
53 | * INITIALIZING, |
||
54 | * INITIALIZED |
||
55 | * }; |
||
56 | * |
||
57 | * static void |
||
58 | * _foo_ready_cb (Foo *self) |
||
59 | * { |
||
60 | * GList *l; |
||
61 | * |
||
62 | * self->priv->state = INITIALIZED; |
||
63 | * |
||
64 | * for (l = self->priv->init_results; l != NULL; l = l->next) |
||
65 | * { |
||
66 | * GTask *task = l->data; |
||
67 | * |
||
68 | * if (self->priv->success) |
||
69 | * g_task_return_boolean (task, TRUE); |
||
70 | * else |
||
71 | * g_task_return_new_error (task, ...); |
||
72 | * g_object_unref (task); |
||
73 | * } |
||
74 | * |
||
75 | * g_list_free (self->priv->init_results); |
||
76 | * self->priv->init_results = NULL; |
||
77 | * } |
||
78 | * |
||
79 | * static void |
||
80 | * foo_init_async (GAsyncInitable *initable, |
||
81 | * int io_priority, |
||
82 | * GCancellable *cancellable, |
||
83 | * GAsyncReadyCallback callback, |
||
84 | * gpointer user_data) |
||
85 | * { |
||
86 | * Foo *self = FOO (initable); |
||
87 | * GTask *task; |
||
88 | * |
||
89 | * task = g_task_new (initable, cancellable, callback, user_data); |
||
90 | * |
||
91 | * switch (self->priv->state) |
||
92 | * { |
||
93 | * case NOT_INITIALIZED: |
||
94 | * _foo_get_ready (self); |
||
95 | * self->priv->init_results = g_list_append (self->priv->init_results, |
||
96 | * task); |
||
97 | * self->priv->state = INITIALIZING; |
||
98 | * break; |
||
99 | * case INITIALIZING: |
||
100 | * self->priv->init_results = g_list_append (self->priv->init_results, |
||
101 | * task); |
||
102 | * break; |
||
103 | * case INITIALIZED: |
||
104 | * if (!self->priv->success) |
||
105 | * g_task_return_new_error (task, ...); |
||
106 | * else |
||
107 | * g_task_return_boolean (task, TRUE); |
||
108 | * g_object_unref (task); |
||
109 | * break; |
||
110 | * } |
||
111 | * } |
||
112 | * |
||
113 | * static gboolean |
||
114 | * foo_init_finish (GAsyncInitable *initable, |
||
115 | * GAsyncResult *result, |
||
116 | * GError **error) |
||
117 | * { |
||
118 | * g_return_val_if_fail (g_task_is_valid (result, initable), FALSE); |
||
119 | * |
||
120 | * return g_task_propagate_boolean (G_TASK (result), error); |
||
121 | * } |
||
122 | * |
||
123 | * static void |
||
124 | * foo_async_initable_iface_init (gpointer g_iface, |
||
125 | * gpointer data) |
||
126 | * { |
||
127 | * GAsyncInitableIface *iface = g_iface; |
||
128 | * |
||
129 | * iface->init_async = foo_init_async; |
||
130 | * iface->init_finish = foo_init_finish; |
||
131 | * } |
||
132 | * ]| |
||
133 | */ |
||
134 | |||
135 | static void g_async_initable_real_init_async (GAsyncInitable *initable, |
||
136 | int io_priority, |
||
137 | GCancellable *cancellable, |
||
138 | GAsyncReadyCallback callback, |
||
139 | gpointer user_data); |
||
140 | static gboolean g_async_initable_real_init_finish (GAsyncInitable *initable, |
||
141 | GAsyncResult *res, |
||
142 | GError **error); |
||
143 | |||
144 | |||
145 | typedef GAsyncInitableIface GAsyncInitableInterface; |
||
146 | G_DEFINE_INTERFACE (GAsyncInitable, g_async_initable, G_TYPE_OBJECT) |
||
147 | |||
148 | |||
149 | static void |
||
150 | g_async_initable_default_init (GAsyncInitableInterface *iface) |
||
151 | { |
||
152 | iface->init_async = g_async_initable_real_init_async; |
||
153 | iface->init_finish = g_async_initable_real_init_finish; |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * g_async_initable_init_async: |
||
158 | * @initable: a #GAsyncInitable. |
||
159 | * @io_priority: the [I/O priority][io-priority] of the operation |
||
160 | * @cancellable: optional #GCancellable object, %NULL to ignore. |
||
161 | * @callback: a #GAsyncReadyCallback to call when the request is satisfied |
||
162 | * @user_data: the data to pass to callback function |
||
163 | * |
||
164 | * Starts asynchronous initialization of the object implementing the |
||
165 | * interface. This must be done before any real use of the object after |
||
166 | * initial construction. If the object also implements #GInitable you can |
||
167 | * optionally call g_initable_init() instead. |
||
168 | * |
||
169 | * When the initialization is finished, @callback will be called. You can |
||
170 | * then call g_async_initable_init_finish() to get the result of the |
||
171 | * initialization. |
||
172 | * |
||
173 | * Implementations may also support cancellation. If @cancellable is not |
||
174 | * %NULL, then initialization can be cancelled by triggering the cancellable |
||
175 | * object from another thread. If the operation was cancelled, the error |
||
176 | * %G_IO_ERROR_CANCELLED will be returned. If @cancellable is not %NULL, and |
||
177 | * the object doesn't support cancellable initialization, the error |
||
178 | * %G_IO_ERROR_NOT_SUPPORTED will be returned. |
||
179 | * |
||
180 | * As with #GInitable, if the object is not initialized, or initialization |
||
181 | * returns with an error, then all operations on the object except |
||
182 | * g_object_ref() and g_object_unref() are considered to be invalid, and |
||
183 | * have undefined behaviour. They will often fail with g_critical() or |
||
184 | * g_warning(), but this must not be relied on. |
||
185 | * |
||
186 | * Implementations of this method must be idempotent: i.e. multiple calls |
||
187 | * to this function with the same argument should return the same results. |
||
188 | * Only the first call initializes the object; further calls return the result |
||
189 | * of the first call. This is so that it's safe to implement the singleton |
||
190 | * pattern in the GObject constructor function. |
||
191 | * |
||
192 | * For classes that also support the #GInitable interface, the default |
||
193 | * implementation of this method will run the g_initable_init() function |
||
194 | * in a thread, so if you want to support asynchronous initialization via |
||
195 | * threads, just implement the #GAsyncInitable interface without overriding |
||
196 | * any interface methods. |
||
197 | * |
||
198 | * Since: 2.22 |
||
199 | */ |
||
200 | void |
||
201 | g_async_initable_init_async (GAsyncInitable *initable, |
||
202 | int io_priority, |
||
203 | GCancellable *cancellable, |
||
204 | GAsyncReadyCallback callback, |
||
205 | gpointer user_data) |
||
206 | { |
||
207 | GAsyncInitableIface *iface; |
||
208 | |||
209 | g_return_if_fail (G_IS_ASYNC_INITABLE (initable)); |
||
210 | |||
211 | iface = G_ASYNC_INITABLE_GET_IFACE (initable); |
||
212 | |||
213 | (* iface->init_async) (initable, io_priority, cancellable, callback, user_data); |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * g_async_initable_init_finish: |
||
218 | * @initable: a #GAsyncInitable. |
||
219 | * @res: a #GAsyncResult. |
||
220 | * @error: a #GError location to store the error occurring, or %NULL to |
||
221 | * ignore. |
||
222 | * |
||
223 | * Finishes asynchronous initialization and returns the result. |
||
224 | * See g_async_initable_init_async(). |
||
225 | * |
||
226 | * Returns: %TRUE if successful. If an error has occurred, this function |
||
227 | * will return %FALSE and set @error appropriately if present. |
||
228 | * |
||
229 | * Since: 2.22 |
||
230 | */ |
||
231 | gboolean |
||
232 | g_async_initable_init_finish (GAsyncInitable *initable, |
||
233 | GAsyncResult *res, |
||
234 | GError **error) |
||
235 | { |
||
236 | GAsyncInitableIface *iface; |
||
237 | |||
238 | g_return_val_if_fail (G_IS_ASYNC_INITABLE (initable), FALSE); |
||
239 | g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE); |
||
240 | |||
241 | if (g_async_result_legacy_propagate_error (res, error)) |
||
242 | return FALSE; |
||
243 | |||
244 | iface = G_ASYNC_INITABLE_GET_IFACE (initable); |
||
245 | |||
246 | return (* iface->init_finish) (initable, res, error); |
||
247 | } |
||
248 | |||
249 | static void |
||
250 | async_init_thread (GTask *task, |
||
251 | gpointer source_object, |
||
252 | gpointer task_data, |
||
253 | GCancellable *cancellable) |
||
254 | { |
||
255 | GError *error = NULL; |
||
256 | |||
257 | if (g_initable_init (G_INITABLE (source_object), cancellable, &error)) |
||
258 | g_task_return_boolean (task, TRUE); |
||
259 | else |
||
260 | g_task_return_error (task, error); |
||
261 | } |
||
262 | |||
263 | static void |
||
264 | g_async_initable_real_init_async (GAsyncInitable *initable, |
||
265 | int io_priority, |
||
266 | GCancellable *cancellable, |
||
267 | GAsyncReadyCallback callback, |
||
268 | gpointer user_data) |
||
269 | { |
||
270 | GTask *task; |
||
271 | |||
272 | g_return_if_fail (G_IS_INITABLE (initable)); |
||
273 | |||
274 | task = g_task_new (initable, cancellable, callback, user_data); |
||
275 | g_task_set_priority (task, io_priority); |
||
276 | g_task_run_in_thread (task, async_init_thread); |
||
277 | g_object_unref (task); |
||
278 | } |
||
279 | |||
280 | static gboolean |
||
281 | g_async_initable_real_init_finish (GAsyncInitable *initable, |
||
282 | GAsyncResult *res, |
||
283 | GError **error) |
||
284 | { |
||
285 | /* For backward compatibility we have to process GSimpleAsyncResults |
||
286 | * even though g_async_initable_real_init_async doesn't generate |
||
287 | * them any more. |
||
288 | */ |
||
289 | G_GNUC_BEGIN_IGNORE_DEPRECATIONS |
||
290 | if (G_IS_SIMPLE_ASYNC_RESULT (res)) |
||
291 | { |
||
292 | GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); |
||
293 | if (g_simple_async_result_propagate_error (simple, error)) |
||
294 | return FALSE; |
||
295 | else |
||
296 | return TRUE; |
||
297 | } |
||
298 | G_GNUC_END_IGNORE_DEPRECATIONS |
||
299 | |||
300 | g_return_val_if_fail (g_task_is_valid (res, initable), FALSE); |
||
301 | |||
302 | return g_task_propagate_boolean (G_TASK (res), error); |
||
303 | } |
||
304 | |||
305 | /** |
||
306 | * g_async_initable_new_async: |
||
307 | * @object_type: a #GType supporting #GAsyncInitable. |
||
308 | * @io_priority: the [I/O priority][io-priority] of the operation |
||
309 | * @cancellable: optional #GCancellable object, %NULL to ignore. |
||
310 | * @callback: a #GAsyncReadyCallback to call when the initialization is |
||
311 | * finished |
||
312 | * @user_data: the data to pass to callback function |
||
313 | * @first_property_name: (allow-none): the name of the first property, or %NULL if no |
||
314 | * properties |
||
315 | * @...: the value of the first property, followed by other property |
||
316 | * value pairs, and ended by %NULL. |
||
317 | * |
||
318 | * Helper function for constructing #GAsyncInitable object. This is |
||
319 | * similar to g_object_new() but also initializes the object asynchronously. |
||
320 | * |
||
321 | * When the initialization is finished, @callback will be called. You can |
||
322 | * then call g_async_initable_new_finish() to get the new object and check |
||
323 | * for any errors. |
||
324 | * |
||
325 | * Since: 2.22 |
||
326 | */ |
||
327 | void |
||
328 | g_async_initable_new_async (GType object_type, |
||
329 | int io_priority, |
||
330 | GCancellable *cancellable, |
||
331 | GAsyncReadyCallback callback, |
||
332 | gpointer user_data, |
||
333 | const gchar *first_property_name, |
||
334 | ...) |
||
335 | { |
||
336 | va_list var_args; |
||
337 | |||
338 | va_start (var_args, first_property_name); |
||
339 | g_async_initable_new_valist_async (object_type, |
||
340 | first_property_name, var_args, |
||
341 | io_priority, cancellable, |
||
342 | callback, user_data); |
||
343 | va_end (var_args); |
||
344 | } |
||
345 | |||
346 | /** |
||
347 | * g_async_initable_newv_async: |
||
348 | * @object_type: a #GType supporting #GAsyncInitable. |
||
349 | * @n_parameters: the number of parameters in @parameters |
||
350 | * @parameters: the parameters to use to construct the object |
||
351 | * @io_priority: the [I/O priority][io-priority] of the operation |
||
352 | * @cancellable: optional #GCancellable object, %NULL to ignore. |
||
353 | * @callback: a #GAsyncReadyCallback to call when the initialization is |
||
354 | * finished |
||
355 | * @user_data: the data to pass to callback function |
||
356 | * |
||
357 | * Helper function for constructing #GAsyncInitable object. This is |
||
358 | * similar to g_object_newv() but also initializes the object asynchronously. |
||
359 | * |
||
360 | * When the initialization is finished, @callback will be called. You can |
||
361 | * then call g_async_initable_new_finish() to get the new object and check |
||
362 | * for any errors. |
||
363 | * |
||
364 | * Since: 2.22 |
||
365 | */ |
||
366 | void |
||
367 | g_async_initable_newv_async (GType object_type, |
||
368 | guint n_parameters, |
||
369 | GParameter *parameters, |
||
370 | int io_priority, |
||
371 | GCancellable *cancellable, |
||
372 | GAsyncReadyCallback callback, |
||
373 | gpointer user_data) |
||
374 | { |
||
375 | GObject *obj; |
||
376 | |||
377 | g_return_if_fail (G_TYPE_IS_ASYNC_INITABLE (object_type)); |
||
378 | |||
379 | obj = g_object_newv (object_type, n_parameters, parameters); |
||
380 | |||
381 | g_async_initable_init_async (G_ASYNC_INITABLE (obj), |
||
382 | io_priority, cancellable, |
||
383 | callback, user_data); |
||
384 | g_object_unref (obj); /* Passed ownership to async call */ |
||
385 | } |
||
386 | |||
387 | /** |
||
388 | * g_async_initable_new_valist_async: |
||
389 | * @object_type: a #GType supporting #GAsyncInitable. |
||
390 | * @first_property_name: the name of the first property, followed by |
||
391 | * the value, and other property value pairs, and ended by %NULL. |
||
392 | * @var_args: The var args list generated from @first_property_name. |
||
393 | * @io_priority: the [I/O priority][io-priority] of the operation |
||
394 | * @cancellable: optional #GCancellable object, %NULL to ignore. |
||
395 | * @callback: a #GAsyncReadyCallback to call when the initialization is |
||
396 | * finished |
||
397 | * @user_data: the data to pass to callback function |
||
398 | * |
||
399 | * Helper function for constructing #GAsyncInitable object. This is |
||
400 | * similar to g_object_new_valist() but also initializes the object |
||
401 | * asynchronously. |
||
402 | * |
||
403 | * When the initialization is finished, @callback will be called. You can |
||
404 | * then call g_async_initable_new_finish() to get the new object and check |
||
405 | * for any errors. |
||
406 | * |
||
407 | * Since: 2.22 |
||
408 | */ |
||
409 | void |
||
410 | g_async_initable_new_valist_async (GType object_type, |
||
411 | const gchar *first_property_name, |
||
412 | va_list var_args, |
||
413 | int io_priority, |
||
414 | GCancellable *cancellable, |
||
415 | GAsyncReadyCallback callback, |
||
416 | gpointer user_data) |
||
417 | { |
||
418 | GObject *obj; |
||
419 | |||
420 | g_return_if_fail (G_TYPE_IS_ASYNC_INITABLE (object_type)); |
||
421 | |||
422 | obj = g_object_new_valist (object_type, |
||
423 | first_property_name, |
||
424 | var_args); |
||
425 | |||
426 | g_async_initable_init_async (G_ASYNC_INITABLE (obj), |
||
427 | io_priority, cancellable, |
||
428 | callback, user_data); |
||
429 | g_object_unref (obj); /* Passed ownership to async call */ |
||
430 | } |
||
431 | |||
432 | /** |
||
433 | * g_async_initable_new_finish: |
||
434 | * @initable: the #GAsyncInitable from the callback |
||
435 | * @res: the #GAsyncResult from the callback |
||
436 | * @error: return location for errors, or %NULL to ignore |
||
437 | * |
||
438 | * Finishes the async construction for the various g_async_initable_new |
||
439 | * calls, returning the created object or %NULL on error. |
||
440 | * |
||
441 | * Returns: (type GObject.Object) (transfer full): a newly created #GObject, |
||
442 | * or %NULL on error. Free with g_object_unref(). |
||
443 | * |
||
444 | * Since: 2.22 |
||
445 | */ |
||
446 | GObject * |
||
447 | g_async_initable_new_finish (GAsyncInitable *initable, |
||
448 | GAsyncResult *res, |
||
449 | GError **error) |
||
450 | { |
||
451 | if (g_async_initable_init_finish (initable, res, error)) |
||
452 | return g_object_ref (initable); |
||
453 | else |
||
454 | return NULL; |
||
455 | } |