gio/ docs/reference/gio Merged gio-standalone into glib.
[platform/upstream/glib.git] / gio / gsimpleasyncresult.c
1 /* GIO - GLib Input, Output and Streaming Library
2  * 
3  * Copyright (C) 2006-2007 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, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
19  *
20  * Author: Alexander Larsson <alexl@redhat.com>
21  */
22
23 #include <config.h>
24
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31
32 #include "gsimpleasyncresult.h"
33 #include "gioscheduler.h"
34 #include <gio/gioerror.h>
35 #include "glibintl.h"
36
37 static void g_simple_async_result_async_result_iface_init (GAsyncResultIface       *iface);
38
39 struct _GSimpleAsyncResult
40 {
41   GObject parent_instance;
42
43   GObject *source_object;
44   GAsyncReadyCallback callback;
45   gpointer user_data;
46   GError *error;
47   gboolean failed;
48   gboolean handle_cancellation;
49
50   gpointer source_tag;
51
52   union {
53     gpointer v_pointer;
54     gboolean v_boolean;
55     gssize   v_ssize;
56   } op_res;
57
58   GDestroyNotify destroy_op_res;
59 };
60
61 struct _GSimpleAsyncResultClass
62 {
63   GObjectClass parent_class;
64 };
65
66
67 G_DEFINE_TYPE_WITH_CODE (GSimpleAsyncResult, g_simple_async_result, G_TYPE_OBJECT,
68                          G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT,
69                                                 g_simple_async_result_async_result_iface_init))
70
71 static void
72 g_simple_async_result_finalize (GObject *object)
73 {
74   GSimpleAsyncResult *simple;
75
76   simple = G_SIMPLE_ASYNC_RESULT (object);
77
78   if (simple->source_object)
79     g_object_unref (simple->source_object);
80
81   if (simple->destroy_op_res)
82     simple->destroy_op_res (simple->op_res.v_pointer);
83
84   if (simple->error)
85     g_error_free (simple->error);
86   
87   if (G_OBJECT_CLASS (g_simple_async_result_parent_class)->finalize)
88     (*G_OBJECT_CLASS (g_simple_async_result_parent_class)->finalize) (object);
89 }
90
91 static void
92 g_simple_async_result_class_init (GSimpleAsyncResultClass *klass)
93 {
94   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
95   
96   gobject_class->finalize = g_simple_async_result_finalize;
97 }
98
99 static void
100 g_simple_async_result_init (GSimpleAsyncResult *simple)
101 {
102   simple->handle_cancellation = TRUE;
103 }
104
105 /**
106  * g_simple_async_result_new:
107  * @source_object:
108  * @callback:
109  * @user_data:
110  * @source_tag:
111  * 
112  * Returns: #GSimpleAsyncResult
113  **/
114 GSimpleAsyncResult *
115 g_simple_async_result_new (GObject *source_object,
116                            GAsyncReadyCallback callback,
117                            gpointer user_data,
118                            gpointer source_tag)
119 {
120   GSimpleAsyncResult *simple;
121
122   g_return_val_if_fail (G_IS_OBJECT (source_object), NULL);
123
124   simple = g_object_new (G_TYPE_SIMPLE_ASYNC_RESULT, NULL);
125   simple->callback = callback;
126   simple->source_object = g_object_ref (source_object);
127   simple->user_data = user_data;
128   simple->source_tag = source_tag;
129   
130   return simple;
131 }
132
133 /**
134  * g_simple_async_result_new_from_error:
135  * @source_object:
136  * @callback:
137  * @user_data:
138  * @error: a #GError location to store the error occuring, or %NULL to 
139  * ignore.
140  * Returns: #GSimpleAsyncResult
141  **/
142 GSimpleAsyncResult *
143 g_simple_async_result_new_from_error (GObject *source_object,
144                                       GAsyncReadyCallback callback,
145                                       gpointer user_data,
146                                       GError *error)
147 {
148   GSimpleAsyncResult *simple;
149
150   g_return_val_if_fail (G_IS_OBJECT (source_object), NULL);
151
152   simple = g_simple_async_result_new (source_object,
153                                       callback,
154                                       user_data, NULL);
155   g_simple_async_result_set_from_error (simple, error);
156
157   return simple;
158 }
159
160 /**
161  * g_simple_async_result_new_error:
162  * @source_object:
163  * @callback:
164  * @user_data:
165  * @domain:
166  * @code:
167  * @format:
168  * @...
169  * 
170  * Returns: #GSimpleAsyncResult.
171  **/
172 GSimpleAsyncResult *
173 g_simple_async_result_new_error (GObject *source_object,
174                                  GAsyncReadyCallback callback,
175                                  gpointer user_data,
176                                  GQuark         domain,
177                                  gint           code,
178                                  const char    *format,
179                                  ...)
180 {
181   GSimpleAsyncResult *simple;
182   va_list args;
183   
184   g_return_val_if_fail (G_IS_OBJECT (source_object), NULL);
185   g_return_val_if_fail (domain != 0, NULL);
186   g_return_val_if_fail (format != NULL, NULL);
187
188   simple = g_simple_async_result_new (source_object,
189                                       callback,
190                                       user_data, NULL);
191
192   va_start (args, format);
193   g_simple_async_result_set_error_va (simple, domain, code, format, args);
194   va_end (args);
195   
196   return simple;
197 }
198
199
200 static gpointer
201 g_simple_async_result_get_user_data (GAsyncResult *res)
202 {
203   return G_SIMPLE_ASYNC_RESULT (res)->user_data;
204 }
205
206 static GObject *
207 g_simple_async_result_get_source_object (GAsyncResult *res)
208 {
209   if (G_SIMPLE_ASYNC_RESULT (res)->source_object)
210     return g_object_ref (G_SIMPLE_ASYNC_RESULT (res)->source_object);
211   return NULL;
212 }
213
214 static void
215 g_simple_async_result_async_result_iface_init (GAsyncResultIface *iface)
216 {
217   iface->get_user_data = g_simple_async_result_get_user_data;
218   iface->get_source_object = g_simple_async_result_get_source_object;
219 }
220
221 /**
222  * g_simple_async_result_set_handle_cancellation:
223  * @simple:
224  * @handle_cancellation:
225  * 
226  **/
227 void
228 g_simple_async_result_set_handle_cancellation (GSimpleAsyncResult *simple,
229                                                gboolean handle_cancellation)
230 {
231   g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple));
232   simple->handle_cancellation = handle_cancellation;
233 }
234
235 /**
236  * g_simple_async_result_get_source_tag:
237  * @simple:
238  * 
239  * Returns: 
240  **/
241 gpointer
242 g_simple_async_result_get_source_tag (GSimpleAsyncResult *simple)
243 {
244   g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple), NULL);
245   return simple->source_tag;
246 }
247
248 /**
249  * g_simple_async_result_result_propagate_error:
250  * @simple:
251  * @dest:
252  * 
253  * Returns: 
254  **/
255 gboolean
256 g_simple_async_result_propagate_error (GSimpleAsyncResult *simple,
257                                        GError **dest)
258 {
259   g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple), FALSE);
260
261   if (simple->failed)
262     {
263       g_propagate_error (dest, simple->error);
264       simple->error = NULL;
265       return TRUE;
266     }
267   return FALSE;
268 }
269
270 /**
271  * g_simple_async_result_set_op_res_gpointer:
272  * @simple:
273  * @op_res:
274  * @destroy_op_res:
275  * 
276  **/
277 void
278 g_simple_async_result_set_op_res_gpointer (GSimpleAsyncResult      *simple,
279                                            gpointer                 op_res,
280                                            GDestroyNotify           destroy_op_res)
281 {
282   g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple));
283
284   simple->op_res.v_pointer = op_res;
285   simple->destroy_op_res = destroy_op_res;
286 }
287
288 /**
289  * g_simple_async_result_get_op_res_gpointer:
290  * @simple:
291  * 
292  * Returns: gpointer.
293  **/
294 gpointer
295 g_simple_async_result_get_op_res_gpointer (GSimpleAsyncResult      *simple)
296 {
297   g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple), NULL);
298   return simple->op_res.v_pointer;
299 }
300
301 /**
302  * g_simple_async_result_set_op_res_gssize:
303  * @simple:
304  * @op_res:
305  * 
306  **/
307 void
308 g_simple_async_result_set_op_res_gssize   (GSimpleAsyncResult      *simple,
309                                            gssize                   op_res)
310 {
311   g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple));
312   simple->op_res.v_ssize = op_res;
313 }
314
315 /**
316  * g_simple_async_result_get_op_res_gssize:
317  * @simple:
318  * 
319  * Returns:
320  **/
321 gssize
322 g_simple_async_result_get_op_res_gssize   (GSimpleAsyncResult      *simple)
323 {
324   g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple), 0);
325   return simple->op_res.v_ssize;
326 }
327
328 /**
329  * g_simple_async_result_set_op_res_gboolean:
330  * @simple:
331  * @op_res:
332  *  
333  **/
334 void
335 g_simple_async_result_set_op_res_gboolean (GSimpleAsyncResult      *simple,
336                                            gboolean                 op_res)
337 {
338   g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple));
339   simple->op_res.v_boolean = !!op_res;
340 }
341
342 /**
343  * g_simple_async_result_get_op_res_gboolean:
344  * @simple:
345  * 
346  * Returns a #gboolean. 
347  **/
348 gboolean
349 g_simple_async_result_get_op_res_gboolean (GSimpleAsyncResult      *simple)
350 {
351   g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple), FALSE);
352   return simple->op_res.v_boolean;
353 }
354
355 /**
356  * g_simple_async_result_set_from_error:
357  * @simple:
358  * @error: #GError.
359  * 
360  * Sets the result from given @error.
361  * 
362  **/
363 void
364 g_simple_async_result_set_from_error (GSimpleAsyncResult *simple,
365                                       GError *error)
366 {
367   g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple));
368   g_return_if_fail (error != NULL);
369
370   simple->error = g_error_copy (error);
371   simple->failed = TRUE;
372 }
373
374 static GError* 
375 _g_error_new_valist (GQuark         domain,
376                     gint           code,
377                     const char    *format,
378                     va_list        args)
379 {
380   GError *error;
381   char *message;
382
383   message = g_strdup_vprintf (format, args);
384
385   error = g_error_new_literal (domain, code, message);
386   g_free (message);
387   
388   return error;
389 }
390
391 /**
392  * g_simple_async_result_set_error_va:
393  * @simple:
394  * @domain:
395  * @code:
396  * @format:
397  * @args: va_list of arguments. 
398  * 
399  * Sets error va_list, suitable for language bindings.
400  * 
401  **/
402 void
403 g_simple_async_result_set_error_va (GSimpleAsyncResult *simple,
404                                     GQuark         domain,
405                                     gint           code,
406                                     const char    *format,
407                                     va_list        args)
408 {
409   g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple));
410   g_return_if_fail (domain != 0);
411   g_return_if_fail (format != NULL);
412
413   simple->error = _g_error_new_valist (domain, code, format, args);
414   simple->failed = TRUE;
415 }
416
417 /**
418  * g_simple_async_result_set_error:
419  * @simple:
420  * @domain:
421  * @code:
422  * @format:
423  * @...
424  * 
425  **/
426 void
427 g_simple_async_result_set_error (GSimpleAsyncResult *simple,
428                                  GQuark         domain,
429                                  gint           code,
430                                  const char    *format,
431                                  ...)
432 {
433   va_list args;
434
435   g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple));
436   g_return_if_fail (domain != 0);
437   g_return_if_fail (format != NULL);
438
439   va_start (args, format);
440   g_simple_async_result_set_error_va (simple, domain, code, format, args);
441   va_end (args);
442 }
443
444 /**
445  * g_simple_async_result_complete:
446  * @simple:
447  * 
448  **/
449 void
450 g_simple_async_result_complete (GSimpleAsyncResult *simple)
451 {
452   g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple));
453
454   if (simple->callback)
455     simple->callback (simple->source_object,
456                       G_ASYNC_RESULT (simple),
457                       simple->user_data);
458 }
459
460 static gboolean
461 complete_in_idle_cb (gpointer data)
462 {
463   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (data);
464
465   g_simple_async_result_complete (simple);
466
467   return FALSE;
468 }
469
470 /**
471  * g_simple_async_result_complete_in_idle:
472  * @simple:
473  *  
474  **/
475 void
476 g_simple_async_result_complete_in_idle (GSimpleAsyncResult *simple)
477 {
478   GSource *source;
479   guint id;
480   
481   g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple));
482   
483   g_object_ref (simple);
484   
485   source = g_idle_source_new ();
486   g_source_set_priority (source, G_PRIORITY_DEFAULT);
487   g_source_set_callback (source, complete_in_idle_cb, simple, g_object_unref);
488
489   id = g_source_attach (source, NULL);
490   g_source_unref (source);
491 }
492
493 typedef struct {
494   GSimpleAsyncResult *simple;
495   GSimpleAsyncThreadFunc func;
496 } RunInThreadData;
497
498 static void
499 run_in_thread (GIOJob *job,
500                GCancellable *c,
501                gpointer _data)
502 {
503   RunInThreadData *data = _data;
504   GSimpleAsyncResult *simple = data->simple;
505
506   if (simple->handle_cancellation &&
507       g_cancellable_is_cancelled (c))
508     {
509        g_simple_async_result_set_error (simple,
510                                         G_IO_ERROR,
511                                         G_IO_ERROR_CANCELLED,
512                                        _("Operation was cancelled"));
513     }
514   else
515     {
516       data->func (simple,
517                   simple->source_object,
518                   c);
519     }
520
521   g_simple_async_result_complete_in_idle (data->simple);
522   g_object_unref (data->simple);
523   g_free (data);
524 }
525
526 /**
527  * g_simple_async_result_run_in_thread:
528  * @simple:
529  * @func:
530  * @io_priority: the io priority of the request.
531  * @cancellable: optional #GCancellable object, %NULL to ignore. 
532  **/
533 void
534 g_simple_async_result_run_in_thread (GSimpleAsyncResult *simple,
535                                      GSimpleAsyncThreadFunc func,
536                                      int io_priority, 
537                                      GCancellable *cancellable)
538 {
539   RunInThreadData *data;
540   
541   g_return_if_fail (G_IS_SIMPLE_ASYNC_RESULT (simple));
542   g_return_if_fail (func != NULL);
543
544   data = g_new (RunInThreadData, 1);
545   data->func = func;
546   data->simple = g_object_ref (simple);
547   g_schedule_io_job (run_in_thread, data, NULL, io_priority, cancellable);
548 }
549
550 /**
551  * g_simple_async_report_error_in_idle:
552  * @object:
553  * @callback:
554  * @user_data:
555  * @domain:
556  * @code:
557  * @format:
558  * @...
559  * 
560  **/
561 void
562 g_simple_async_report_error_in_idle (GObject *object,
563                                      GAsyncReadyCallback callback,
564                                      gpointer user_data,
565                                      GQuark         domain,
566                                      gint           code,
567                                      const char    *format,
568                                      ...)
569 {
570   GSimpleAsyncResult *simple;
571   va_list args;
572   
573   g_return_if_fail (G_IS_OBJECT (object));
574   g_return_if_fail (domain != 0);
575   g_return_if_fail (format != NULL);
576
577   simple = g_simple_async_result_new (object,
578                                       callback,
579                                       user_data, NULL);
580
581   va_start (args, format);
582   g_simple_async_result_set_error_va (simple, domain, code, format, args);
583   va_end (args);
584   g_simple_async_result_complete_in_idle (simple);
585   g_object_unref (simple);
586 }