Add a lot of missing annotations
[platform/upstream/glib.git] / gio / goutputstream.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 #include "goutputstream.h"
25 #include "gcancellable.h"
26 #include "gasyncresult.h"
27 #include "gsimpleasyncresult.h"
28 #include "ginputstream.h"
29 #include "gioerror.h"
30 #include "glibintl.h"
31
32
33 /**
34  * SECTION:goutputstream
35  * @short_description: Base class for implementing streaming output
36  * @include: gio/gio.h
37  *
38  * GOutputStream has functions to write to a stream (g_output_stream_write()),
39  * to close a stream (g_output_stream_close()) and to flush pending writes
40  * (g_output_stream_flush()). 
41  *
42  * To copy the content of an input stream to an output stream without 
43  * manually handling the reads and writes, use g_output_stream_splice(). 
44  *
45  * All of these functions have async variants too.
46  **/
47
48 G_DEFINE_ABSTRACT_TYPE (GOutputStream, g_output_stream, G_TYPE_OBJECT);
49
50 struct _GOutputStreamPrivate {
51   guint closed : 1;
52   guint pending : 1;
53   guint closing : 1;
54   GAsyncReadyCallback outstanding_callback;
55 };
56
57 static gssize   g_output_stream_real_splice        (GOutputStream             *stream,
58                                                     GInputStream              *source,
59                                                     GOutputStreamSpliceFlags   flags,
60                                                     GCancellable              *cancellable,
61                                                     GError                   **error);
62 static void     g_output_stream_real_write_async   (GOutputStream             *stream,
63                                                     const void                *buffer,
64                                                     gsize                      count,
65                                                     int                        io_priority,
66                                                     GCancellable              *cancellable,
67                                                     GAsyncReadyCallback        callback,
68                                                     gpointer                   data);
69 static gssize   g_output_stream_real_write_finish  (GOutputStream             *stream,
70                                                     GAsyncResult              *result,
71                                                     GError                   **error);
72 static void     g_output_stream_real_splice_async  (GOutputStream             *stream,
73                                                     GInputStream              *source,
74                                                     GOutputStreamSpliceFlags   flags,
75                                                     int                        io_priority,
76                                                     GCancellable              *cancellable,
77                                                     GAsyncReadyCallback        callback,
78                                                     gpointer                   data);
79 static gssize   g_output_stream_real_splice_finish (GOutputStream             *stream,
80                                                     GAsyncResult              *result,
81                                                     GError                   **error);
82 static void     g_output_stream_real_flush_async   (GOutputStream             *stream,
83                                                     int                        io_priority,
84                                                     GCancellable              *cancellable,
85                                                     GAsyncReadyCallback        callback,
86                                                     gpointer                   data);
87 static gboolean g_output_stream_real_flush_finish  (GOutputStream             *stream,
88                                                     GAsyncResult              *result,
89                                                     GError                   **error);
90 static void     g_output_stream_real_close_async   (GOutputStream             *stream,
91                                                     int                        io_priority,
92                                                     GCancellable              *cancellable,
93                                                     GAsyncReadyCallback        callback,
94                                                     gpointer                   data);
95 static gboolean g_output_stream_real_close_finish  (GOutputStream             *stream,
96                                                     GAsyncResult              *result,
97                                                     GError                   **error);
98
99 static void
100 g_output_stream_finalize (GObject *object)
101 {
102   G_OBJECT_CLASS (g_output_stream_parent_class)->finalize (object);
103 }
104
105 static void
106 g_output_stream_dispose (GObject *object)
107 {
108   GOutputStream *stream;
109
110   stream = G_OUTPUT_STREAM (object);
111   
112   if (!stream->priv->closed)
113     g_output_stream_close (stream, NULL, NULL);
114
115   G_OBJECT_CLASS (g_output_stream_parent_class)->dispose (object);
116 }
117
118 static void
119 g_output_stream_class_init (GOutputStreamClass *klass)
120 {
121   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
122   
123   g_type_class_add_private (klass, sizeof (GOutputStreamPrivate));
124   
125   gobject_class->finalize = g_output_stream_finalize;
126   gobject_class->dispose = g_output_stream_dispose;
127
128   klass->splice = g_output_stream_real_splice;
129   
130   klass->write_async = g_output_stream_real_write_async;
131   klass->write_finish = g_output_stream_real_write_finish;
132   klass->splice_async = g_output_stream_real_splice_async;
133   klass->splice_finish = g_output_stream_real_splice_finish;
134   klass->flush_async = g_output_stream_real_flush_async;
135   klass->flush_finish = g_output_stream_real_flush_finish;
136   klass->close_async = g_output_stream_real_close_async;
137   klass->close_finish = g_output_stream_real_close_finish;
138 }
139
140 static void
141 g_output_stream_init (GOutputStream *stream)
142 {
143   stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
144                                               G_TYPE_OUTPUT_STREAM,
145                                               GOutputStreamPrivate);
146 }
147
148 /**
149  * g_output_stream_write:
150  * @stream: a #GOutputStream.
151  * @buffer: (array length=count) (element-type guint8): the buffer containing the data to write. 
152  * @count: the number of bytes to write
153  * @cancellable: optional cancellable object
154  * @error: location to store the error occuring, or %NULL to ignore
155  *
156  * Tries to write @count bytes from @buffer into the stream. Will block
157  * during the operation.
158  * 
159  * If count is 0, returns 0 and does nothing. A value of @count
160  * larger than %G_MAXSSIZE will cause a %G_IO_ERROR_INVALID_ARGUMENT error.
161  *
162  * On success, the number of bytes written to the stream is returned.
163  * It is not an error if this is not the same as the requested size, as it
164  * can happen e.g. on a partial I/O error, or if there is not enough
165  * storage in the stream. All writes block until at least one byte
166  * is written or an error occurs; 0 is never returned (unless
167  * @count is 0).
168  * 
169  * If @cancellable is not NULL, then the operation can be cancelled by
170  * triggering the cancellable object from another thread. If the operation
171  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. If an
172  * operation was partially finished when the operation was cancelled the
173  * partial result will be returned, without an error.
174  *
175  * On error -1 is returned and @error is set accordingly.
176  * 
177  * Return value: Number of bytes written, or -1 on error
178  **/
179 gssize
180 g_output_stream_write (GOutputStream  *stream,
181                        const void     *buffer,
182                        gsize           count,
183                        GCancellable   *cancellable,
184                        GError        **error)
185 {
186   GOutputStreamClass *class;
187   gssize res;
188
189   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), -1);
190   g_return_val_if_fail (buffer != NULL, 0);
191
192   if (count == 0)
193     return 0;
194   
195   if (((gssize) count) < 0)
196     {
197       g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
198                    _("Too large count value passed to %s"), G_STRFUNC);
199       return -1;
200     }
201
202   class = G_OUTPUT_STREAM_GET_CLASS (stream);
203
204   if (class->write_fn == NULL) 
205     {
206       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
207                            _("Output stream doesn't implement write"));
208       return -1;
209     }
210   
211   if (!g_output_stream_set_pending (stream, error))
212     return -1;
213   
214   if (cancellable)
215     g_cancellable_push_current (cancellable);
216   
217   res = class->write_fn (stream, buffer, count, cancellable, error);
218   
219   if (cancellable)
220     g_cancellable_pop_current (cancellable);
221   
222   g_output_stream_clear_pending (stream);
223
224   return res; 
225 }
226
227 /**
228  * g_output_stream_write_all:
229  * @stream: a #GOutputStream.
230  * @buffer: (array length=count) (element-type guint8): the buffer containing the data to write. 
231  * @count: the number of bytes to write
232  * @bytes_written: location to store the number of bytes that was 
233  *     written to the stream
234  * @cancellable: optional #GCancellable object, %NULL to ignore.
235  * @error: location to store the error occuring, or %NULL to ignore
236  *
237  * Tries to write @count bytes from @buffer into the stream. Will block
238  * during the operation.
239  * 
240  * This function is similar to g_output_stream_write(), except it tries to
241  * write as many bytes as requested, only stopping on an error.
242  *
243  * On a successful write of @count bytes, %TRUE is returned, and @bytes_written
244  * is set to @count.
245  * 
246  * If there is an error during the operation FALSE is returned and @error
247  * is set to indicate the error status, @bytes_written is updated to contain
248  * the number of bytes written into the stream before the error occurred.
249  *
250  * Return value: %TRUE on success, %FALSE if there was an error
251  **/
252 gboolean
253 g_output_stream_write_all (GOutputStream  *stream,
254                            const void     *buffer,
255                            gsize           count,
256                            gsize          *bytes_written,
257                            GCancellable   *cancellable,
258                            GError        **error)
259 {
260   gsize _bytes_written;
261   gssize res;
262
263   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
264   g_return_val_if_fail (buffer != NULL, FALSE);
265
266   _bytes_written = 0;
267   while (_bytes_written < count)
268     {
269       res = g_output_stream_write (stream, (char *)buffer + _bytes_written, count - _bytes_written,
270                                    cancellable, error);
271       if (res == -1)
272         {
273           if (bytes_written)
274             *bytes_written = _bytes_written;
275           return FALSE;
276         }
277       
278       if (res == 0)
279         g_warning ("Write returned zero without error");
280
281       _bytes_written += res;
282     }
283   
284   if (bytes_written)
285     *bytes_written = _bytes_written;
286
287   return TRUE;
288 }
289
290 /**
291  * g_output_stream_flush:
292  * @stream: a #GOutputStream.
293  * @cancellable: optional cancellable object
294  * @error: location to store the error occuring, or %NULL to ignore
295  *
296  * Flushed any outstanding buffers in the stream. Will block during 
297  * the operation. Closing the stream will implicitly cause a flush.
298  *
299  * This function is optional for inherited classes.
300  * 
301  * If @cancellable is not %NULL, then the operation can be cancelled by
302  * triggering the cancellable object from another thread. If the operation
303  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
304  *
305  * Return value: %TRUE on success, %FALSE on error
306  **/
307 gboolean
308 g_output_stream_flush (GOutputStream  *stream,
309                        GCancellable   *cancellable,
310                        GError        **error)
311 {
312   GOutputStreamClass *class;
313   gboolean res;
314
315   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
316
317   if (!g_output_stream_set_pending (stream, error))
318     return FALSE;
319   
320   class = G_OUTPUT_STREAM_GET_CLASS (stream);
321
322   res = TRUE;
323   if (class->flush)
324     {
325       if (cancellable)
326         g_cancellable_push_current (cancellable);
327       
328       res = class->flush (stream, cancellable, error);
329       
330       if (cancellable)
331         g_cancellable_pop_current (cancellable);
332     }
333   
334   g_output_stream_clear_pending (stream);
335
336   return res;
337 }
338
339 /**
340  * g_output_stream_splice:
341  * @stream: a #GOutputStream.
342  * @source: a #GInputStream.
343  * @flags: a set of #GOutputStreamSpliceFlags.
344  * @cancellable: optional #GCancellable object, %NULL to ignore.
345  * @error: a #GError location to store the error occuring, or %NULL to
346  * ignore.
347  *
348  * Splices an input stream into an output stream.
349  *
350  * Returns: a #gssize containing the size of the data spliced, or
351  *     -1 if an error occurred.
352  **/
353 gssize
354 g_output_stream_splice (GOutputStream             *stream,
355                         GInputStream              *source,
356                         GOutputStreamSpliceFlags   flags,
357                         GCancellable              *cancellable,
358                         GError                   **error)
359 {
360   GOutputStreamClass *class;
361   gssize bytes_copied;
362
363   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), -1);
364   g_return_val_if_fail (G_IS_INPUT_STREAM (source), -1);
365
366   if (g_input_stream_is_closed (source))
367     {
368       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
369                            _("Source stream is already closed"));
370       return -1;
371     }
372
373   if (!g_output_stream_set_pending (stream, error))
374     return -1;
375
376   class = G_OUTPUT_STREAM_GET_CLASS (stream);
377
378   if (cancellable)
379     g_cancellable_push_current (cancellable);
380
381   bytes_copied = class->splice (stream, source, flags, cancellable, error);
382
383   if (cancellable)
384     g_cancellable_pop_current (cancellable);
385
386   g_output_stream_clear_pending (stream);
387
388   return bytes_copied;
389 }
390
391 static gssize
392 g_output_stream_real_splice (GOutputStream             *stream,
393                              GInputStream              *source,
394                              GOutputStreamSpliceFlags   flags,
395                              GCancellable              *cancellable,
396                              GError                   **error)
397 {
398   GOutputStreamClass *class = G_OUTPUT_STREAM_GET_CLASS (stream);
399   gssize n_read, n_written;
400   gssize bytes_copied;
401   char buffer[8192], *p;
402   gboolean res;
403
404   bytes_copied = 0;
405   if (class->write_fn == NULL)
406     {
407       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
408                            _("Output stream doesn't implement write"));
409       res = FALSE;
410       goto notsupported;
411     }
412
413   res = TRUE;
414   do
415     {
416       n_read = g_input_stream_read (source, buffer, sizeof (buffer), cancellable, error);
417       if (n_read == -1)
418         {
419           res = FALSE;
420           break;
421         }
422
423       if (n_read == 0)
424         break;
425
426       p = buffer;
427       while (n_read > 0)
428         {
429           n_written = class->write_fn (stream, p, n_read, cancellable, error);
430           if (n_written == -1)
431             {
432               res = FALSE;
433               break;
434             }
435
436           p += n_written;
437           n_read -= n_written;
438           bytes_copied += n_written;
439         }
440     }
441   while (res);
442
443  notsupported:
444   if (!res)
445     error = NULL; /* Ignore further errors */
446
447   if (flags & G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE)
448     {
449       /* Don't care about errors in source here */
450       g_input_stream_close (source, cancellable, NULL);
451     }
452
453   if (flags & G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET)
454     {
455       /* But write errors on close are bad! */
456       if (class->close_fn &&
457           !class->close_fn (stream, cancellable, error))
458         res = FALSE;
459     }
460
461   if (res)
462     return bytes_copied;
463
464   return -1;
465 }
466
467
468 /**
469  * g_output_stream_close:
470  * @stream: A #GOutputStream.
471  * @cancellable: optional cancellable object
472  * @error: location to store the error occuring, or %NULL to ignore
473  *
474  * Closes the stream, releasing resources related to it.
475  *
476  * Once the stream is closed, all other operations will return %G_IO_ERROR_CLOSED.
477  * Closing a stream multiple times will not return an error.
478  *
479  * Closing a stream will automatically flush any outstanding buffers in the
480  * stream.
481  *
482  * Streams will be automatically closed when the last reference
483  * is dropped, but you might want to call this function to make sure 
484  * resources are released as early as possible.
485  *
486  * Some streams might keep the backing store of the stream (e.g. a file descriptor)
487  * open after the stream is closed. See the documentation for the individual
488  * stream for details.
489  *
490  * On failure the first error that happened will be reported, but the close
491  * operation will finish as much as possible. A stream that failed to
492  * close will still return %G_IO_ERROR_CLOSED for all operations. Still, it
493  * is important to check and report the error to the user, otherwise
494  * there might be a loss of data as all data might not be written.
495  * 
496  * If @cancellable is not NULL, then the operation can be cancelled by
497  * triggering the cancellable object from another thread. If the operation
498  * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned.
499  * Cancelling a close will still leave the stream closed, but there some streams
500  * can use a faster close that doesn't block to e.g. check errors. On
501  * cancellation (as with any error) there is no guarantee that all written
502  * data will reach the target. 
503  *
504  * Return value: %TRUE on success, %FALSE on failure
505  **/
506 gboolean
507 g_output_stream_close (GOutputStream  *stream,
508                        GCancellable   *cancellable,
509                        GError        **error)
510 {
511   GOutputStreamClass *class;
512   gboolean res;
513
514   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
515
516   class = G_OUTPUT_STREAM_GET_CLASS (stream);
517
518   if (stream->priv->closed)
519     return TRUE;
520
521   if (!g_output_stream_set_pending (stream, error))
522     return FALSE;
523
524   stream->priv->closing = TRUE;
525
526   if (cancellable)
527     g_cancellable_push_current (cancellable);
528
529   if (class->flush)
530     res = class->flush (stream, cancellable, error);
531   else
532     res = TRUE;
533   
534   if (!res)
535     {
536       /* flushing caused the error that we want to return,
537        * but we still want to close the underlying stream if possible
538        */
539       if (class->close_fn)
540         class->close_fn (stream, cancellable, NULL);
541     }
542   else
543     {
544       res = TRUE;
545       if (class->close_fn)
546         res = class->close_fn (stream, cancellable, error);
547     }
548   
549   if (cancellable)
550     g_cancellable_pop_current (cancellable);
551
552   stream->priv->closing = FALSE;
553   stream->priv->closed = TRUE;
554   g_output_stream_clear_pending (stream);
555   
556   return res;
557 }
558
559 static void
560 async_ready_callback_wrapper (GObject      *source_object,
561                               GAsyncResult *res,
562                               gpointer      user_data)
563 {
564   GOutputStream *stream = G_OUTPUT_STREAM (source_object);
565
566   g_output_stream_clear_pending (stream);
567   if (stream->priv->outstanding_callback)
568     (*stream->priv->outstanding_callback) (source_object, res, user_data);
569   g_object_unref (stream);
570 }
571
572 typedef struct {
573   gint io_priority;
574   GCancellable *cancellable;
575   GError *flush_error;
576   gpointer user_data;
577 } CloseUserData;
578
579 static void
580 async_ready_close_callback_wrapper (GObject      *source_object,
581                                     GAsyncResult *res,
582                                     gpointer      user_data)
583 {
584   GOutputStream *stream = G_OUTPUT_STREAM (source_object);
585   CloseUserData *data = user_data;
586
587   stream->priv->closing = FALSE;
588   stream->priv->closed = TRUE;
589
590   g_output_stream_clear_pending (stream);
591
592   if (stream->priv->outstanding_callback)
593     {
594       if (data->flush_error != NULL)
595         {
596           GSimpleAsyncResult *err;
597
598           err = g_simple_async_result_new_from_error (source_object,
599                                                       stream->priv->outstanding_callback,
600                                                       data->user_data,
601                                                       data->flush_error);
602
603           (*stream->priv->outstanding_callback) (source_object,
604                                                  G_ASYNC_RESULT (err),
605                                                  data->user_data);
606           g_object_unref (err);
607         }
608       else
609         {
610           (*stream->priv->outstanding_callback) (source_object,
611                                                  res,
612                                                  data->user_data);
613         }
614     }
615
616   g_object_unref (stream);
617
618   if (data->cancellable)
619     g_object_unref (data->cancellable);
620
621   if (data->flush_error)
622     g_error_free (data->flush_error);
623
624   g_slice_free (CloseUserData, data);
625 }
626
627 static void
628 async_ready_close_flushed_callback_wrapper (GObject      *source_object,
629                                             GAsyncResult *res,
630                                             gpointer      user_data)
631 {
632   GOutputStream *stream = G_OUTPUT_STREAM (source_object);
633   GOutputStreamClass *class;
634   CloseUserData *data = user_data;
635   GSimpleAsyncResult *simple;
636
637   /* propagate the possible error */
638   if (G_IS_SIMPLE_ASYNC_RESULT (res))
639     {
640       simple = G_SIMPLE_ASYNC_RESULT (res);
641       g_simple_async_result_propagate_error (simple, &data->flush_error);
642     }
643
644   class = G_OUTPUT_STREAM_GET_CLASS (stream);
645
646   /* we still close, even if there was a flush error */
647   class->close_async (stream, data->io_priority, data->cancellable,
648                       async_ready_close_callback_wrapper, user_data);
649 }
650
651 /**
652  * g_output_stream_write_async:
653  * @stream: A #GOutputStream.
654  * @buffer: (array length=count) (element-type guint8): the buffer containing the data to write. 
655  * @count: the number of bytes to write
656  * @io_priority: the io priority of the request.
657  * @cancellable: optional #GCancellable object, %NULL to ignore.
658  * @callback: callback to call when the request is satisfied
659  * @user_data: the data to pass to callback function
660  *
661  * Request an asynchronous write of @count bytes from @buffer into 
662  * the stream. When the operation is finished @callback will be called.
663  * You can then call g_output_stream_write_finish() to get the result of the 
664  * operation.
665  *
666  * During an async request no other sync and async calls are allowed, 
667  * and will result in %G_IO_ERROR_PENDING errors. 
668  *
669  * A value of @count larger than %G_MAXSSIZE will cause a 
670  * %G_IO_ERROR_INVALID_ARGUMENT error.
671  *
672  * On success, the number of bytes written will be passed to the
673  * @callback. It is not an error if this is not the same as the 
674  * requested size, as it can happen e.g. on a partial I/O error, 
675  * but generally we try to write as many bytes as requested. 
676  *
677  * You are guaranteed that this method will never fail with
678  * %G_IO_ERROR_WOULD_BLOCK - if @stream can't accept more data, the
679  * method will just wait until this changes.
680  *
681  * Any outstanding I/O request with higher priority (lower numerical 
682  * value) will be executed before an outstanding request with lower 
683  * priority. Default priority is %G_PRIORITY_DEFAULT.
684  *
685  * The asyncronous methods have a default fallback that uses threads 
686  * to implement asynchronicity, so they are optional for inheriting 
687  * classes. However, if you override one you must override all.
688  *
689  * For the synchronous, blocking version of this function, see 
690  * g_output_stream_write().
691  **/
692 void
693 g_output_stream_write_async (GOutputStream       *stream,
694                              const void          *buffer,
695                              gsize                count,
696                              int                  io_priority,
697                              GCancellable        *cancellable,
698                              GAsyncReadyCallback  callback,
699                              gpointer             user_data)
700 {
701   GOutputStreamClass *class;
702   GSimpleAsyncResult *simple;
703   GError *error = NULL;
704
705   g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
706   g_return_if_fail (buffer != NULL);
707
708   if (count == 0)
709     {
710       simple = g_simple_async_result_new (G_OBJECT (stream),
711                                           callback,
712                                           user_data,
713                                           g_output_stream_write_async);
714       g_simple_async_result_complete_in_idle (simple);
715       g_object_unref (simple);
716       return;
717     }
718
719   if (((gssize) count) < 0)
720     {
721       g_simple_async_report_error_in_idle (G_OBJECT (stream),
722                                            callback,
723                                            user_data,
724                                            G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
725                                            _("Too large count value passed to %s"),
726                                            G_STRFUNC);
727       return;
728     }
729
730   if (!g_output_stream_set_pending (stream, &error))
731     {
732       g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
733                                             callback,
734                                             user_data,
735                                             error);
736       g_error_free (error);
737       return;
738     }
739   
740   class = G_OUTPUT_STREAM_GET_CLASS (stream);
741
742   stream->priv->outstanding_callback = callback;
743   g_object_ref (stream);
744   class->write_async (stream, buffer, count, io_priority, cancellable,
745                       async_ready_callback_wrapper, user_data);
746 }
747
748 /**
749  * g_output_stream_write_finish:
750  * @stream: a #GOutputStream.
751  * @result: a #GAsyncResult.
752  * @error: a #GError location to store the error occuring, or %NULL to 
753  * ignore.
754  * 
755  * Finishes a stream write operation.
756  * 
757  * Returns: a #gssize containing the number of bytes written to the stream.
758  **/
759 gssize
760 g_output_stream_write_finish (GOutputStream  *stream,
761                               GAsyncResult   *result,
762                               GError        **error)
763 {
764   GSimpleAsyncResult *simple;
765   GOutputStreamClass *class;
766
767   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), -1);
768   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), -1);
769
770   if (G_IS_SIMPLE_ASYNC_RESULT (result))
771     {
772       simple = G_SIMPLE_ASYNC_RESULT (result);
773       if (g_simple_async_result_propagate_error (simple, error))
774         return -1;
775
776       /* Special case writes of 0 bytes */
777       if (g_simple_async_result_get_source_tag (simple) == g_output_stream_write_async)
778         return 0;
779     }
780   
781   class = G_OUTPUT_STREAM_GET_CLASS (stream);
782   return class->write_finish (stream, result, error);
783 }
784
785 typedef struct {
786   GInputStream *source;
787   gpointer user_data;
788   GAsyncReadyCallback callback;
789 } SpliceUserData;
790
791 static void
792 async_ready_splice_callback_wrapper (GObject      *source_object,
793                                      GAsyncResult *res,
794                                      gpointer     _data)
795 {
796   GOutputStream *stream = G_OUTPUT_STREAM (source_object);
797   SpliceUserData *data = _data;
798   
799   g_output_stream_clear_pending (stream);
800   
801   if (data->callback)
802     (*data->callback) (source_object, res, data->user_data);
803   
804   g_object_unref (stream);
805   g_object_unref (data->source);
806   g_free (data);
807 }
808
809 /**
810  * g_output_stream_splice_async:
811  * @stream: a #GOutputStream.
812  * @source: a #GInputStream. 
813  * @flags: a set of #GOutputStreamSpliceFlags.
814  * @io_priority: the io priority of the request.
815  * @cancellable: optional #GCancellable object, %NULL to ignore. 
816  * @callback: a #GAsyncReadyCallback. 
817  * @user_data: user data passed to @callback.
818  * 
819  * Splices a stream asynchronously.
820  * When the operation is finished @callback will be called.
821  * You can then call g_output_stream_splice_finish() to get the 
822  * result of the operation.
823  *
824  * For the synchronous, blocking version of this function, see 
825  * g_output_stream_splice().
826  **/
827 void
828 g_output_stream_splice_async (GOutputStream            *stream,
829                               GInputStream             *source,
830                               GOutputStreamSpliceFlags  flags,
831                               int                       io_priority,
832                               GCancellable             *cancellable,
833                               GAsyncReadyCallback       callback,
834                               gpointer                  user_data)
835 {
836   GOutputStreamClass *class;
837   SpliceUserData *data;
838   GError *error = NULL;
839
840   g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
841   g_return_if_fail (G_IS_INPUT_STREAM (source));
842
843   if (g_input_stream_is_closed (source))
844     {
845       g_simple_async_report_error_in_idle (G_OBJECT (stream),
846                                            callback,
847                                            user_data,
848                                            G_IO_ERROR, G_IO_ERROR_CLOSED,
849                                            _("Source stream is already closed"));
850       return;
851     }
852   
853   if (!g_output_stream_set_pending (stream, &error))
854     {
855       g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
856                                             callback,
857                                             user_data,
858                                             error);
859       g_error_free (error);
860       return;
861     }
862
863   class = G_OUTPUT_STREAM_GET_CLASS (stream);
864
865   data = g_new0 (SpliceUserData, 1);
866   data->callback = callback;
867   data->user_data = user_data;
868   data->source = g_object_ref (source);
869   
870   g_object_ref (stream);
871   class->splice_async (stream, source, flags, io_priority, cancellable,
872                       async_ready_splice_callback_wrapper, data);
873 }
874
875 /**
876  * g_output_stream_splice_finish:
877  * @stream: a #GOutputStream.
878  * @result: a #GAsyncResult.
879  * @error: a #GError location to store the error occuring, or %NULL to 
880  * ignore.
881  *
882  * Finishes an asynchronous stream splice operation.
883  * 
884  * Returns: a #gssize of the number of bytes spliced.
885  **/
886 gssize
887 g_output_stream_splice_finish (GOutputStream  *stream,
888                                GAsyncResult   *result,
889                                GError        **error)
890 {
891   GSimpleAsyncResult *simple;
892   GOutputStreamClass *class;
893
894   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), -1);
895   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), -1);
896
897   if (G_IS_SIMPLE_ASYNC_RESULT (result))
898     {
899       simple = G_SIMPLE_ASYNC_RESULT (result);
900       if (g_simple_async_result_propagate_error (simple, error))
901         return -1;
902     }
903   
904   class = G_OUTPUT_STREAM_GET_CLASS (stream);
905   return class->splice_finish (stream, result, error);
906 }
907
908 /**
909  * g_output_stream_flush_async:
910  * @stream: a #GOutputStream.
911  * @io_priority: the io priority of the request.
912  * @cancellable: optional #GCancellable object, %NULL to ignore.
913  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
914  * @user_data: the data to pass to callback function
915  * 
916  * Flushes a stream asynchronously.
917  * For behaviour details see g_output_stream_flush().
918  *
919  * When the operation is finished @callback will be 
920  * called. You can then call g_output_stream_flush_finish() to get the 
921  * result of the operation.
922  **/
923 void
924 g_output_stream_flush_async (GOutputStream       *stream,
925                              int                  io_priority,
926                              GCancellable        *cancellable,
927                              GAsyncReadyCallback  callback,
928                              gpointer             user_data)
929 {
930   GOutputStreamClass *class;
931   GSimpleAsyncResult *simple;
932   GError *error = NULL;
933
934   g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
935
936   if (!g_output_stream_set_pending (stream, &error))
937     {
938       g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
939                                             callback,
940                                             user_data,
941                                             error);
942       g_error_free (error);
943       return;
944     }
945
946   stream->priv->outstanding_callback = callback;
947   g_object_ref (stream);
948
949   class = G_OUTPUT_STREAM_GET_CLASS (stream);
950   
951   if (class->flush_async == NULL)
952     {
953       simple = g_simple_async_result_new (G_OBJECT (stream),
954                                           async_ready_callback_wrapper,
955                                           user_data,
956                                           g_output_stream_flush_async);
957       g_simple_async_result_complete_in_idle (simple);
958       g_object_unref (simple);
959       return;
960     }
961       
962   class->flush_async (stream, io_priority, cancellable,
963                       async_ready_callback_wrapper, user_data);
964 }
965
966 /**
967  * g_output_stream_flush_finish:
968  * @stream: a #GOutputStream.
969  * @result: a GAsyncResult.
970  * @error: a #GError location to store the error occuring, or %NULL to 
971  * ignore.
972  * 
973  * Finishes flushing an output stream.
974  * 
975  * Returns: %TRUE if flush operation suceeded, %FALSE otherwise.
976  **/
977 gboolean
978 g_output_stream_flush_finish (GOutputStream  *stream,
979                               GAsyncResult   *result,
980                               GError        **error)
981 {
982   GSimpleAsyncResult *simple;
983   GOutputStreamClass *klass;
984
985   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
986   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
987
988   if (G_IS_SIMPLE_ASYNC_RESULT (result))
989     {
990       simple = G_SIMPLE_ASYNC_RESULT (result);
991       if (g_simple_async_result_propagate_error (simple, error))
992         return FALSE;
993
994       /* Special case default implementation */
995       if (g_simple_async_result_get_source_tag (simple) == g_output_stream_flush_async)
996         return TRUE;
997     }
998
999   klass = G_OUTPUT_STREAM_GET_CLASS (stream);
1000   return klass->flush_finish (stream, result, error);
1001 }
1002
1003
1004 /**
1005  * g_output_stream_close_async:
1006  * @stream: A #GOutputStream.
1007  * @io_priority: the io priority of the request.
1008  * @callback: callback to call when the request is satisfied
1009  * @user_data: the data to pass to callback function
1010  * @cancellable: optional cancellable object
1011  *
1012  * Requests an asynchronous close of the stream, releasing resources 
1013  * related to it. When the operation is finished @callback will be 
1014  * called. You can then call g_output_stream_close_finish() to get 
1015  * the result of the operation.
1016  *
1017  * For behaviour details see g_output_stream_close().
1018  *
1019  * The asyncronous methods have a default fallback that uses threads 
1020  * to implement asynchronicity, so they are optional for inheriting 
1021  * classes. However, if you override one you must override all.
1022  **/
1023 void
1024 g_output_stream_close_async (GOutputStream       *stream,
1025                              int                  io_priority,
1026                              GCancellable        *cancellable,
1027                              GAsyncReadyCallback  callback,
1028                              gpointer             user_data)
1029 {
1030   GOutputStreamClass *class;
1031   GSimpleAsyncResult *simple;
1032   GError *error = NULL;
1033   CloseUserData *data;
1034
1035   g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
1036   
1037   if (stream->priv->closed)
1038     {
1039       simple = g_simple_async_result_new (G_OBJECT (stream),
1040                                           callback,
1041                                           user_data,
1042                                           g_output_stream_close_async);
1043       g_simple_async_result_complete_in_idle (simple);
1044       g_object_unref (simple);
1045       return;
1046     }
1047
1048   if (!g_output_stream_set_pending (stream, &error))
1049     {
1050       g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
1051                                             callback,
1052                                             user_data,
1053                                             error);
1054       g_error_free (error);
1055       return;
1056     }
1057   
1058   class = G_OUTPUT_STREAM_GET_CLASS (stream);
1059   stream->priv->closing = TRUE;
1060   stream->priv->outstanding_callback = callback;
1061   g_object_ref (stream);
1062
1063   data = g_slice_new0 (CloseUserData);
1064
1065   if (cancellable != NULL)
1066     data->cancellable = g_object_ref (cancellable);
1067
1068   data->io_priority = io_priority;
1069   data->user_data = user_data;
1070
1071   /* Call close_async directly if there is no need to flush, or if the flush
1072      can be done sync (in the output stream async close thread) */
1073   if (class->flush_async == NULL ||
1074       (class->flush_async == g_output_stream_real_flush_async &&
1075        (class->flush == NULL || class->close_async == g_output_stream_real_close_async)))
1076     {
1077       class->close_async (stream, io_priority, cancellable,
1078                           async_ready_close_callback_wrapper, data);
1079     }
1080   else
1081     {
1082       /* First do an async flush, then do the async close in the callback
1083          wrapper (see async_ready_close_flushed_callback_wrapper) */
1084       class->flush_async (stream, io_priority, cancellable,
1085                           async_ready_close_flushed_callback_wrapper, data);
1086     }
1087 }
1088
1089 /**
1090  * g_output_stream_close_finish:
1091  * @stream: a #GOutputStream.
1092  * @result: a #GAsyncResult.
1093  * @error: a #GError location to store the error occuring, or %NULL to 
1094  * ignore.
1095  * 
1096  * Closes an output stream.
1097  * 
1098  * Returns: %TRUE if stream was successfully closed, %FALSE otherwise.
1099  **/
1100 gboolean
1101 g_output_stream_close_finish (GOutputStream  *stream,
1102                               GAsyncResult   *result,
1103                               GError        **error)
1104 {
1105   GSimpleAsyncResult *simple;
1106   GOutputStreamClass *class;
1107
1108   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
1109   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
1110
1111   if (G_IS_SIMPLE_ASYNC_RESULT (result))
1112     {
1113       simple = G_SIMPLE_ASYNC_RESULT (result);
1114       if (g_simple_async_result_propagate_error (simple, error))
1115         return FALSE;
1116
1117       /* Special case already closed */
1118       if (g_simple_async_result_get_source_tag (simple) == g_output_stream_close_async)
1119         return TRUE;
1120     }
1121
1122   class = G_OUTPUT_STREAM_GET_CLASS (stream);
1123   return class->close_finish (stream, result, error);
1124 }
1125
1126 /**
1127  * g_output_stream_is_closed:
1128  * @stream: a #GOutputStream.
1129  * 
1130  * Checks if an output stream has already been closed.
1131  * 
1132  * Returns: %TRUE if @stream is closed. %FALSE otherwise. 
1133  **/
1134 gboolean
1135 g_output_stream_is_closed (GOutputStream *stream)
1136 {
1137   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), TRUE);
1138   
1139   return stream->priv->closed;
1140 }
1141
1142 /**
1143  * g_output_stream_is_closing:
1144  * @stream: a #GOutputStream.
1145  *
1146  * Checks if an output stream is being closed. This can be
1147  * used inside e.g. a flush implementation to see if the
1148  * flush (or other i/o operation) is called from within
1149  * the closing operation.
1150  *
1151  * Returns: %TRUE if @stream is being closed. %FALSE otherwise.
1152  *
1153  * Since: 2.24
1154  **/
1155 gboolean
1156 g_output_stream_is_closing (GOutputStream *stream)
1157 {
1158   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), TRUE);
1159
1160   return stream->priv->closing;
1161 }
1162
1163 /**
1164  * g_output_stream_has_pending:
1165  * @stream: a #GOutputStream.
1166  * 
1167  * Checks if an ouput stream has pending actions.
1168  * 
1169  * Returns: %TRUE if @stream has pending actions. 
1170  **/
1171 gboolean
1172 g_output_stream_has_pending (GOutputStream *stream)
1173 {
1174   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
1175   
1176   return stream->priv->pending;
1177 }
1178
1179 /**
1180  * g_output_stream_set_pending:
1181  * @stream: a #GOutputStream.
1182  * @error: a #GError location to store the error occuring, or %NULL to 
1183  * ignore.
1184  * 
1185  * Sets @stream to have actions pending. If the pending flag is
1186  * already set or @stream is closed, it will return %FALSE and set
1187  * @error.
1188  *
1189  * Return value: %TRUE if pending was previously unset and is now set.
1190  **/
1191 gboolean
1192 g_output_stream_set_pending (GOutputStream *stream,
1193                              GError **error)
1194 {
1195   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
1196   
1197   if (stream->priv->closed)
1198     {
1199       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
1200                            _("Stream is already closed"));
1201       return FALSE;
1202     }
1203   
1204   if (stream->priv->pending)
1205     {
1206       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
1207                            /* Translators: This is an error you get if there is
1208                             * already an operation running against this stream when
1209                             * you try to start one */
1210                            _("Stream has outstanding operation"));
1211       return FALSE;
1212     }
1213   
1214   stream->priv->pending = TRUE;
1215   return TRUE;
1216 }
1217
1218 /**
1219  * g_output_stream_clear_pending:
1220  * @stream: output stream
1221  * 
1222  * Clears the pending flag on @stream.
1223  **/
1224 void
1225 g_output_stream_clear_pending (GOutputStream *stream)
1226 {
1227   g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
1228   
1229   stream->priv->pending = FALSE;
1230 }
1231
1232
1233 /********************************************
1234  *   Default implementation of async ops    *
1235  ********************************************/
1236
1237 typedef struct {
1238   const void         *buffer;
1239   gsize               count_requested;
1240   gssize              count_written;
1241 } WriteData;
1242
1243 static void
1244 write_async_thread (GSimpleAsyncResult *res,
1245                     GObject            *object,
1246                     GCancellable       *cancellable)
1247 {
1248   WriteData *op;
1249   GOutputStreamClass *class;
1250   GError *error = NULL;
1251
1252   class = G_OUTPUT_STREAM_GET_CLASS (object);
1253   op = g_simple_async_result_get_op_res_gpointer (res);
1254   op->count_written = class->write_fn (G_OUTPUT_STREAM (object), op->buffer, op->count_requested,
1255                                        cancellable, &error);
1256   if (op->count_written == -1)
1257     {
1258       g_simple_async_result_set_from_error (res, error);
1259       g_error_free (error);
1260     }
1261 }
1262
1263 static void
1264 g_output_stream_real_write_async (GOutputStream       *stream,
1265                                   const void          *buffer,
1266                                   gsize                count,
1267                                   int                  io_priority,
1268                                   GCancellable        *cancellable,
1269                                   GAsyncReadyCallback  callback,
1270                                   gpointer             user_data)
1271 {
1272   GSimpleAsyncResult *res;
1273   WriteData *op;
1274
1275   op = g_new0 (WriteData, 1);
1276   res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_write_async);
1277   g_simple_async_result_set_op_res_gpointer (res, op, g_free);
1278   op->buffer = buffer;
1279   op->count_requested = count;
1280   
1281   g_simple_async_result_run_in_thread (res, write_async_thread, io_priority, cancellable);
1282   g_object_unref (res);
1283 }
1284
1285 static gssize
1286 g_output_stream_real_write_finish (GOutputStream  *stream,
1287                                    GAsyncResult   *result,
1288                                    GError        **error)
1289 {
1290   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
1291   WriteData *op;
1292
1293   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_output_stream_real_write_async);
1294   op = g_simple_async_result_get_op_res_gpointer (simple);
1295   return op->count_written;
1296 }
1297
1298 typedef struct {
1299   GInputStream *source;
1300   GOutputStreamSpliceFlags flags;
1301   gssize bytes_copied;
1302 } SpliceData;
1303
1304 static void
1305 splice_async_thread (GSimpleAsyncResult *result,
1306                      GObject            *object,
1307                      GCancellable       *cancellable)
1308 {
1309   SpliceData *op;
1310   GOutputStreamClass *class;
1311   GError *error = NULL;
1312   GOutputStream *stream;
1313
1314   stream = G_OUTPUT_STREAM (object);
1315   class = G_OUTPUT_STREAM_GET_CLASS (object);
1316   op = g_simple_async_result_get_op_res_gpointer (result);
1317   
1318   op->bytes_copied = class->splice (stream,
1319                                     op->source,
1320                                     op->flags,
1321                                     cancellable,
1322                                     &error);
1323   if (op->bytes_copied == -1)
1324     {
1325       g_simple_async_result_set_from_error (result, error);
1326       g_error_free (error);
1327     }
1328 }
1329
1330 static void
1331 g_output_stream_real_splice_async (GOutputStream             *stream,
1332                                    GInputStream              *source,
1333                                    GOutputStreamSpliceFlags   flags,
1334                                    int                        io_priority,
1335                                    GCancellable              *cancellable,
1336                                    GAsyncReadyCallback        callback,
1337                                    gpointer                   user_data)
1338 {
1339   GSimpleAsyncResult *res;
1340   SpliceData *op;
1341
1342   op = g_new0 (SpliceData, 1);
1343   res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_splice_async);
1344   g_simple_async_result_set_op_res_gpointer (res, op, g_free);
1345   op->flags = flags;
1346   op->source = source;
1347
1348   /* TODO: In the case where both source and destintion have
1349      non-threadbased async calls we can use a true async copy here */
1350   
1351   g_simple_async_result_run_in_thread (res, splice_async_thread, io_priority, cancellable);
1352   g_object_unref (res);
1353 }
1354
1355 static gssize
1356 g_output_stream_real_splice_finish (GOutputStream  *stream,
1357                                     GAsyncResult   *result,
1358                                     GError        **error)
1359 {
1360   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
1361   SpliceData *op;
1362
1363   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_output_stream_real_splice_async);
1364   op = g_simple_async_result_get_op_res_gpointer (simple);
1365   return op->bytes_copied;
1366 }
1367
1368
1369 static void
1370 flush_async_thread (GSimpleAsyncResult *res,
1371                     GObject            *object,
1372                     GCancellable       *cancellable)
1373 {
1374   GOutputStreamClass *class;
1375   gboolean result;
1376   GError *error = NULL;
1377
1378   class = G_OUTPUT_STREAM_GET_CLASS (object);
1379   result = TRUE;
1380   if (class->flush)
1381     result = class->flush (G_OUTPUT_STREAM (object), cancellable, &error);
1382
1383   if (!result)
1384     {
1385       g_simple_async_result_set_from_error (res, error);
1386       g_error_free (error);
1387     }
1388 }
1389
1390 static void
1391 g_output_stream_real_flush_async (GOutputStream       *stream,
1392                                   int                  io_priority,
1393                                   GCancellable        *cancellable,
1394                                   GAsyncReadyCallback  callback,
1395                                   gpointer             user_data)
1396 {
1397   GSimpleAsyncResult *res;
1398
1399   res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_write_async);
1400   
1401   g_simple_async_result_run_in_thread (res, flush_async_thread, io_priority, cancellable);
1402   g_object_unref (res);
1403 }
1404
1405 static gboolean
1406 g_output_stream_real_flush_finish (GOutputStream  *stream,
1407                                    GAsyncResult   *result,
1408                                    GError        **error)
1409 {
1410   return TRUE;
1411 }
1412
1413 static void
1414 close_async_thread (GSimpleAsyncResult *res,
1415                     GObject            *object,
1416                     GCancellable       *cancellable)
1417 {
1418   GOutputStreamClass *class;
1419   GError *error = NULL;
1420   gboolean result = TRUE;
1421
1422   class = G_OUTPUT_STREAM_GET_CLASS (object);
1423
1424   /* Do a flush here if there is a flush function, and we did not have to do
1425      an async flush before (see g_output_stream_close_async) */
1426   if (class->flush != NULL &&
1427       (class->flush_async == NULL ||
1428        class->flush_async == g_output_stream_real_flush_async))
1429     {
1430       result = class->flush (G_OUTPUT_STREAM (object), cancellable, &error);
1431     }
1432
1433   /* Auto handling of cancelation disabled, and ignore
1434      cancellation, since we want to close things anyway, although
1435      possibly in a quick-n-dirty way. At least we never want to leak
1436      open handles */
1437   
1438   if (class->close_fn)
1439     {
1440       /* Make sure to close, even if the flush failed (see sync close) */
1441       if (!result)
1442         class->close_fn (G_OUTPUT_STREAM (object), cancellable, NULL);
1443       else
1444         result = class->close_fn (G_OUTPUT_STREAM (object), cancellable, &error);
1445
1446       if (!result)
1447         {
1448           g_simple_async_result_set_from_error (res, error);
1449           g_error_free (error);
1450         }
1451     }
1452 }
1453
1454 static void
1455 g_output_stream_real_close_async (GOutputStream       *stream,
1456                                   int                  io_priority,
1457                                   GCancellable        *cancellable,
1458                                   GAsyncReadyCallback  callback,
1459                                   gpointer             user_data)
1460 {
1461   GSimpleAsyncResult *res;
1462   
1463   res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_close_async);
1464
1465   g_simple_async_result_set_handle_cancellation (res, FALSE);
1466   
1467   g_simple_async_result_run_in_thread (res, close_async_thread, io_priority, cancellable);
1468   g_object_unref (res);
1469 }
1470
1471 static gboolean
1472 g_output_stream_real_close_finish (GOutputStream  *stream,
1473                                    GAsyncResult   *result,
1474                                    GError        **error)
1475 {
1476   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
1477   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_output_stream_real_close_async);
1478   return TRUE;
1479 }