1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2006-2007 Red Hat, Inc.
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.
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.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: Alexander Larsson <alexl@redhat.com>
25 #include <sys/types.h>
34 #include "gsimpleasyncresult.h"
35 #include "gioscheduler.h"
36 #include <gio/gioerror.h>
42 * SECTION:gsimpleasyncresult
43 * @short_description: Simple asynchronous results implementation
45 * @see_also: #GAsyncResult
47 * Implements #GAsyncResult for simple cases. Most of the time, this
48 * will be all an application needs, and will be used transparently.
49 * Because of this, #GSimpleAsyncResult is used throughout GIO for
50 * handling asynchronous functions.
52 * GSimpleAsyncResult handles #GAsyncReadyCallback<!-- -->s, error
53 * reporting, operation cancellation and the final state of an operation,
54 * completely transparent to the application. Results can be returned
55 * as a pointer e.g. for functions that return data that is collected
56 * asynchronously, a boolean value for checking the success or failure
57 * of an operation, or a #gssize for operations which return the number
58 * of bytes modified by the operation; all of the simple return cases
61 * Most of the time, an application will not need to know of the details
62 * of this API; it is handled transparently, and any necessary operations
63 * are handled by #GAsyncResult's interface. However, if implementing a
64 * new GIO module, for writing language bindings, or for complex
65 * applications that need better control of how asynchronous operations
66 * are completed, it is important to understand this functionality.
68 * GSimpleAsyncResults are tagged with the calling function to ensure
69 * that asynchronous functions and their finishing functions are used
72 * To create a new #GSimpleAsyncResult, call g_simple_async_result_new().
73 * If the result needs to be created for a #GError, use
74 * g_simple_async_result_new_from_error(). If a #GError is not available
75 * (e.g. the asynchronous operation's doesn't take a #GError argument),
76 * but the result still needs to be created for an error condition, use
77 * g_simple_async_result_new_error() (or g_simple_async_result_set_error_va()
78 * if your application or binding requires passing a variable argument list
79 * directly), and the error can then be propegated through the use of
80 * g_simple_async_result_propagate_error().
82 * An asynchronous operation can be made to ignore a cancellation event by
83 * calling g_simple_async_result_set_handle_cancellation() with a
84 * #GSimpleAsyncResult for the operation and %FALSE.
86 * GSimpleAsyncResult can integrate into GLib's event loop, #GMainLoop,
87 * or it can use #GThread<!-- -->s if available.
88 * g_simple_async_result_complete() will finish an I/O task directly within
89 * the main event loop. g_simple_async_result_complete_in_idle() will
90 * integrate the I/O task into the main event loop as an idle function and
91 * g_simple_async_result_run_in_thread() will run the job in a separate
94 * To set the results of an asynchronous function,
95 * g_simple_async_result_set_op_res_gpointer(),
96 * g_simple_async_result_set_op_res_gboolean(), and
97 * g_simple_async_result_set_op_res_gssize()
98 * are provided, setting the operation's result to a gpointer, gboolean, or
99 * gssize, respectively.
101 * Likewise, to get the result of an asynchronous function,
102 * g_simple_async_result_get_op_res_gpointer(),
103 * g_simple_async_result_get_op_res_gboolean(), and
104 * g_simple_async_result_get_op_res_gssize() are
105 * provided, getting the operation's result as a gpointer, gboolean, and
106 * gssize, respectively.
109 static void g_simple_async_result_async_result_iface_init (GAsyncResultIface
*iface
);
111 struct _GSimpleAsyncResult
113 GObject parent_instance
;
115 GObject
*source_object
;
116 GAsyncReadyCallback callback
;
120 gboolean handle_cancellation
;
130 GDestroyNotify destroy_op_res
;
133 struct _GSimpleAsyncResultClass
135 GObjectClass parent_class
;
139 G_DEFINE_TYPE_WITH_CODE (GSimpleAsyncResult
, g_simple_async_result
, G_TYPE_OBJECT
,
140 G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT
,
141 g_simple_async_result_async_result_iface_init
))
144 g_simple_async_result_finalize (GObject
*object
)
146 GSimpleAsyncResult
*simple
;
148 simple
= G_SIMPLE_ASYNC_RESULT (object
);
150 if (simple
->source_object
)
151 g_object_unref (simple
->source_object
);
153 if (simple
->destroy_op_res
)
154 simple
->destroy_op_res (simple
->op_res
.v_pointer
);
157 g_error_free (simple
->error
);
159 if (G_OBJECT_CLASS (g_simple_async_result_parent_class
)->finalize
)
160 (*G_OBJECT_CLASS (g_simple_async_result_parent_class
)->finalize
) (object
);
164 g_simple_async_result_class_init (GSimpleAsyncResultClass
*klass
)
166 GObjectClass
*gobject_class
= G_OBJECT_CLASS (klass
);
168 gobject_class
->finalize
= g_simple_async_result_finalize
;
172 g_simple_async_result_init (GSimpleAsyncResult
*simple
)
174 simple
->handle_cancellation
= TRUE
;
178 * g_simple_async_result_new:
179 * @source_object: a #GObject the asynchronous function was called with.
180 * @callback: a #GAsyncReadyCallback.
181 * @user_data: user data passed to @callback.
182 * @source_tag: the asynchronous function.
184 * Creates a #GSimpleAsyncResult.
186 * Returns: a #GSimpleAsyncResult.
189 g_simple_async_result_new (GObject
*source_object
,
190 GAsyncReadyCallback callback
,
194 GSimpleAsyncResult
*simple
;
196 g_return_val_if_fail (G_IS_OBJECT (source_object
), NULL
);
198 simple
= g_object_new (G_TYPE_SIMPLE_ASYNC_RESULT
, NULL
);
199 simple
->callback
= callback
;
200 simple
->source_object
= g_object_ref (source_object
);
201 simple
->user_data
= user_data
;
202 simple
->source_tag
= source_tag
;
208 * g_simple_async_result_new_from_error:
209 * @source_object: a #GObject.
210 * @callback: a #GAsyncReadyCallback.
211 * @user_data: user data passed to @callback.
212 * @error: a #GError location.
214 * Creates a #GSimpleAsyncResult from an error condition.
216 * Returns: a #GSimpleAsyncResult.
219 g_simple_async_result_new_from_error (GObject
*source_object
,
220 GAsyncReadyCallback callback
,
224 GSimpleAsyncResult
*simple
;
226 g_return_val_if_fail (G_IS_OBJECT (source_object
), NULL
);
228 simple
= g_simple_async_result_new (source_object
,
231 g_simple_async_result_set_from_error (simple
, error
);
237 * g_simple_async_result_new_error:
238 * @source_object: a #GObject.
239 * @callback: a #GAsyncReadyCallback.
240 * @user_data: user data passed to @callback.
241 * @domain: a #GQuark.
242 * @code: an error code.
243 * @format: a string with format characters.
244 * @...: a list of values to insert into @format.
246 * Creates a new #GSimpleAsyncResult with a set error.
248 * Returns: a #GSimpleAsyncResult.
251 g_simple_async_result_new_error (GObject
*source_object
,
252 GAsyncReadyCallback callback
,
259 GSimpleAsyncResult
*simple
;
262 g_return_val_if_fail (G_IS_OBJECT (source_object
), NULL
);
263 g_return_val_if_fail (domain
!= 0, NULL
);
264 g_return_val_if_fail (format
!= NULL
, NULL
);
266 simple
= g_simple_async_result_new (source_object
,
270 va_start (args
, format
);
271 g_simple_async_result_set_error_va (simple
, domain
, code
, format
, args
);
279 g_simple_async_result_get_user_data (GAsyncResult
*res
)
281 return G_SIMPLE_ASYNC_RESULT (res
)->user_data
;
285 g_simple_async_result_get_source_object (GAsyncResult
*res
)
287 if (G_SIMPLE_ASYNC_RESULT (res
)->source_object
)
288 return g_object_ref (G_SIMPLE_ASYNC_RESULT (res
)->source_object
);
293 g_simple_async_result_async_result_iface_init (GAsyncResultIface
*iface
)
295 iface
->get_user_data
= g_simple_async_result_get_user_data
;
296 iface
->get_source_object
= g_simple_async_result_get_source_object
;
300 * g_simple_async_result_set_handle_cancellation:
301 * @simple: a #GSimpleAsyncResult.
302 * @handle_cancellation: a #gboolean.
304 * Sets whether to handle cancellation within the asynchronous operation.
308 g_simple_async_result_set_handle_cancellation (GSimpleAsyncResult
*simple
,
309 gboolean handle_cancellation
)
311 g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple
));
312 simple
->handle_cancellation
= handle_cancellation
;
316 * g_simple_async_result_get_source_tag:
317 * @simple: a #GSimpleAsyncResult.
319 * Gets the source tag for the #GSimpleAsyncResult.
321 * Returns: a #gpointer to the source object for the #GSimpleAsyncResult.
324 g_simple_async_result_get_source_tag (GSimpleAsyncResult
*simple
)
326 g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple
), NULL
);
327 return simple
->source_tag
;
331 * g_simple_async_result_propagate_error:
332 * @simple: a #GSimpleAsyncResult.
333 * @dest: a location to propegate the error to.
335 * Propagates an error from within the simple asynchronous result to
336 * a given destination.
338 * Returns: %TRUE if the error was propegated to @dest. %FALSE otherwise.
341 g_simple_async_result_propagate_error (GSimpleAsyncResult
*simple
,
344 g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple
), FALSE
);
348 g_propagate_error (dest
, simple
->error
);
349 simple
->error
= NULL
;
357 * g_simple_async_result_set_op_res_gpointer:
358 * @simple: a #GSimpleAsyncResult.
359 * @op_res: a pointer result from an asynchronous function.
360 * @destroy_op_res: a #GDestroyNotify function.
362 * Sets the operation result within the asynchronous result to a pointer.
365 g_simple_async_result_set_op_res_gpointer (GSimpleAsyncResult
*simple
,
367 GDestroyNotify destroy_op_res
)
369 g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple
));
371 simple
->op_res
.v_pointer
= op_res
;
372 simple
->destroy_op_res
= destroy_op_res
;
376 * g_simple_async_result_get_op_res_gpointer:
377 * @simple: a #GSimpleAsyncResult.
379 * Gets a pointer result as returned by the asynchronous function.
381 * Returns: a pointer from the result.
384 g_simple_async_result_get_op_res_gpointer (GSimpleAsyncResult
*simple
)
386 g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple
), NULL
);
387 return simple
->op_res
.v_pointer
;
391 * g_simple_async_result_set_op_res_gssize:
392 * @simple: a #GSimpleAsyncResult.
393 * @op_res: a #gssize.
395 * Sets the operation result within the asynchronous result to
399 g_simple_async_result_set_op_res_gssize (GSimpleAsyncResult
*simple
,
402 g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple
));
403 simple
->op_res
.v_ssize
= op_res
;
407 * g_simple_async_result_get_op_res_gssize:
408 * @simple: a #GSimpleAsyncResult.
410 * Gets a gssize from the asynchronous result.
412 * Returns: a gssize returned from the asynchronous function.
415 g_simple_async_result_get_op_res_gssize (GSimpleAsyncResult
*simple
)
417 g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple
), 0);
418 return simple
->op_res
.v_ssize
;
422 * g_simple_async_result_set_op_res_gboolean:
423 * @simple: a #GSimpleAsyncResult.
424 * @op_res: a #gboolean.
426 * Sets the operation result to a boolean within the asynchronous result.
429 g_simple_async_result_set_op_res_gboolean (GSimpleAsyncResult
*simple
,
432 g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple
));
433 simple
->op_res
.v_boolean
= !!op_res
;
437 * g_simple_async_result_get_op_res_gboolean:
438 * @simple: a #GSimpleAsyncResult.
440 * Gets the operation result boolean from within the asynchronous result.
442 * Returns: %TRUE if the operation's result was %TRUE, %FALSE
443 * if the operation's result was %FALSE.
446 g_simple_async_result_get_op_res_gboolean (GSimpleAsyncResult
*simple
)
448 g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple
), FALSE
);
449 return simple
->op_res
.v_boolean
;
453 * g_simple_async_result_set_from_error:
454 * @simple: a #GSimpleAsyncResult.
457 * Sets the result from a #GError.
460 g_simple_async_result_set_from_error (GSimpleAsyncResult
*simple
,
463 g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple
));
464 g_return_if_fail (error
!= NULL
);
466 simple
->error
= g_error_copy (error
);
467 simple
->failed
= TRUE
;
471 _g_error_new_valist (GQuark domain
,
479 message
= g_strdup_vprintf (format
, args
);
481 error
= g_error_new_literal (domain
, code
, message
);
488 * g_simple_async_result_set_error_va:
489 * @simple: a #GSimpleAsyncResult.
490 * @domain: a #GQuark (usually #G_IO_ERROR).
491 * @code: an error code.
492 * @format: a formatted error reporting string.
493 * @args: va_list of arguments.
495 * Sets an error within the asynchronous result without a #GError.
496 * Unless writing a binding, see g_simple_async_result_set_error().
499 g_simple_async_result_set_error_va (GSimpleAsyncResult
*simple
,
505 g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple
));
506 g_return_if_fail (domain
!= 0);
507 g_return_if_fail (format
!= NULL
);
509 simple
->error
= _g_error_new_valist (domain
, code
, format
, args
);
510 simple
->failed
= TRUE
;
514 * g_simple_async_result_set_error:
515 * @simple: a #GSimpleAsyncResult.
516 * @domain: a #GQuark (usually #G_IO_ERROR).
517 * @code: an error code.
518 * @format: a formatted error reporting string.
519 * @...: a list of variables to fill in @format.
521 * Sets an error within the asynchronous result without a #GError.
524 g_simple_async_result_set_error (GSimpleAsyncResult
*simple
,
532 g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple
));
533 g_return_if_fail (domain
!= 0);
534 g_return_if_fail (format
!= NULL
);
536 va_start (args
, format
);
537 g_simple_async_result_set_error_va (simple
, domain
, code
, format
, args
);
542 * g_simple_async_result_complete:
543 * @simple: a #GSimpleAsyncResult.
545 * Completes an asynchronous I/O job.
548 g_simple_async_result_complete (GSimpleAsyncResult
*simple
)
550 g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple
));
552 if (simple
->callback
)
553 simple
->callback (simple
->source_object
,
554 G_ASYNC_RESULT (simple
),
559 complete_in_idle_cb (gpointer data
)
561 GSimpleAsyncResult
*simple
= G_SIMPLE_ASYNC_RESULT (data
);
563 g_simple_async_result_complete (simple
);
569 * g_simple_async_result_complete_in_idle:
570 * @simple: a #GSimpleAsyncResult.
572 * Completes an asynchronous function in the main event loop using
576 g_simple_async_result_complete_in_idle (GSimpleAsyncResult
*simple
)
581 g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple
));
583 g_object_ref (simple
);
585 source
= g_idle_source_new ();
586 g_source_set_priority (source
, G_PRIORITY_DEFAULT
);
587 g_source_set_callback (source
, complete_in_idle_cb
, simple
, g_object_unref
);
589 id
= g_source_attach (source
, NULL
);
590 g_source_unref (source
);
594 GSimpleAsyncResult
*simple
;
595 GSimpleAsyncThreadFunc func
;
599 run_in_thread (GIOSchedulerJob
*job
,
603 RunInThreadData
*data
= _data
;
604 GSimpleAsyncResult
*simple
= data
->simple
;
606 if (simple
->handle_cancellation
&&
607 g_cancellable_is_cancelled (c
))
608 g_simple_async_result_set_error (simple
,
610 G_IO_ERROR_CANCELLED
,
611 _("Operation was cancelled"));
614 simple
->source_object
,
617 g_simple_async_result_complete_in_idle (data
->simple
);
618 g_object_unref (data
->simple
);
625 * g_simple_async_result_run_in_thread:
626 * @simple: a #GSimpleAsyncResult.
627 * @func: a #GSimpleAsyncThreadFunc.
628 * @io_priority: the io priority of the request.
629 * @cancellable: optional #GCancellable object, %NULL to ignore.
631 * Runs the asynchronous job in a separated thread.
634 g_simple_async_result_run_in_thread (GSimpleAsyncResult
*simple
,
635 GSimpleAsyncThreadFunc func
,
637 GCancellable
*cancellable
)
639 RunInThreadData
*data
;
641 g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple
));
642 g_return_if_fail (func
!= NULL
);
644 data
= g_new (RunInThreadData
, 1);
646 data
->simple
= g_object_ref (simple
);
647 g_io_scheduler_push_job (run_in_thread
, data
, NULL
, io_priority
, cancellable
);
651 * g_simple_async_report_error_in_idle:
652 * @object: a #GObject.
653 * @callback: a #GAsyncReadyCallback.
654 * @user_data: user data passed to @callback.
655 * @domain: a #GQuark containing the error domain (usually #G_IO_ERROR).
656 * @code: a specific error code.
657 * @format: a formatted error reporting string.
658 * @...: a list of variables to fill in @format.
660 * Reports an error in an asynchronous function in an idle function by
661 * directly setting the contents of the #GAsyncResult with the given error
665 g_simple_async_report_error_in_idle (GObject
*object
,
666 GAsyncReadyCallback callback
,
673 GSimpleAsyncResult
*simple
;
676 g_return_if_fail (G_IS_OBJECT (object
));
677 g_return_if_fail (domain
!= 0);
678 g_return_if_fail (format
!= NULL
);
680 simple
= g_simple_async_result_new (object
,
684 va_start (args
, format
);
685 g_simple_async_result_set_error_va (simple
, domain
, code
, format
, args
);
687 g_simple_async_result_complete_in_idle (simple
);
688 g_object_unref (simple
);
692 * g_simple_async_report_gerror_in_idle:
693 * @object: a #GObject.
694 * @callback: a #GAsyncReadyCallback.
695 * @user_data: user data passed to @callback.
696 * @error: the #GError to report
698 * Reports an error in an idle function. Similar to
699 * g_simple_async_report_error_in_idle(), but takes a #GError rather
700 * than building a new one.
703 g_simple_async_report_gerror_in_idle (GObject
*object
,
704 GAsyncReadyCallback callback
,
708 GSimpleAsyncResult
*simple
;
710 g_return_if_fail (G_IS_OBJECT (object
));
711 g_return_if_fail (error
!= NULL
);
713 simple
= g_simple_async_result_new_from_error (object
,
717 g_simple_async_result_complete_in_idle (simple
);
718 g_object_unref (simple
);
721 #define __G_SIMPLE_ASYNC_RESULT_C__
722 #include "gioaliasdef.c"