Use g_simple_async_result_{new_,}take_error
[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_take_error (source_object,
599                                                       stream->priv->outstanding_callback,
600                                                       data->user_data,
601                                                       data->flush_error);
602           data->flush_error = NULL;
603
604           (*stream->priv->outstanding_callback) (source_object,
605                                                  G_ASYNC_RESULT (err),
606                                                  data->user_data);
607           g_object_unref (err);
608         }
609       else
610         {
611           (*stream->priv->outstanding_callback) (source_object,
612                                                  res,
613                                                  data->user_data);
614         }
615     }
616
617   g_object_unref (stream);
618
619   if (data->cancellable)
620     g_object_unref (data->cancellable);
621
622   if (data->flush_error)
623     g_error_free (data->flush_error);
624
625   g_slice_free (CloseUserData, data);
626 }
627
628 static void
629 async_ready_close_flushed_callback_wrapper (GObject      *source_object,
630                                             GAsyncResult *res,
631                                             gpointer      user_data)
632 {
633   GOutputStream *stream = G_OUTPUT_STREAM (source_object);
634   GOutputStreamClass *class;
635   CloseUserData *data = user_data;
636   GSimpleAsyncResult *simple;
637
638   /* propagate the possible error */
639   if (G_IS_SIMPLE_ASYNC_RESULT (res))
640     {
641       simple = G_SIMPLE_ASYNC_RESULT (res);
642       g_simple_async_result_propagate_error (simple, &data->flush_error);
643     }
644
645   class = G_OUTPUT_STREAM_GET_CLASS (stream);
646
647   /* we still close, even if there was a flush error */
648   class->close_async (stream, data->io_priority, data->cancellable,
649                       async_ready_close_callback_wrapper, user_data);
650 }
651
652 /**
653  * g_output_stream_write_async:
654  * @stream: A #GOutputStream.
655  * @buffer: (array length=count) (element-type guint8): the buffer containing the data to write. 
656  * @count: the number of bytes to write
657  * @io_priority: the io priority of the request.
658  * @cancellable: optional #GCancellable object, %NULL to ignore.
659  * @callback: callback to call when the request is satisfied
660  * @user_data: the data to pass to callback function
661  *
662  * Request an asynchronous write of @count bytes from @buffer into 
663  * the stream. When the operation is finished @callback will be called.
664  * You can then call g_output_stream_write_finish() to get the result of the 
665  * operation.
666  *
667  * During an async request no other sync and async calls are allowed, 
668  * and will result in %G_IO_ERROR_PENDING errors. 
669  *
670  * A value of @count larger than %G_MAXSSIZE will cause a 
671  * %G_IO_ERROR_INVALID_ARGUMENT error.
672  *
673  * On success, the number of bytes written will be passed to the
674  * @callback. It is not an error if this is not the same as the 
675  * requested size, as it can happen e.g. on a partial I/O error, 
676  * but generally we try to write as many bytes as requested. 
677  *
678  * You are guaranteed that this method will never fail with
679  * %G_IO_ERROR_WOULD_BLOCK - if @stream can't accept more data, the
680  * method will just wait until this changes.
681  *
682  * Any outstanding I/O request with higher priority (lower numerical 
683  * value) will be executed before an outstanding request with lower 
684  * priority. Default priority is %G_PRIORITY_DEFAULT.
685  *
686  * The asyncronous methods have a default fallback that uses threads 
687  * to implement asynchronicity, so they are optional for inheriting 
688  * classes. However, if you override one you must override all.
689  *
690  * For the synchronous, blocking version of this function, see 
691  * g_output_stream_write().
692  **/
693 void
694 g_output_stream_write_async (GOutputStream       *stream,
695                              const void          *buffer,
696                              gsize                count,
697                              int                  io_priority,
698                              GCancellable        *cancellable,
699                              GAsyncReadyCallback  callback,
700                              gpointer             user_data)
701 {
702   GOutputStreamClass *class;
703   GSimpleAsyncResult *simple;
704   GError *error = NULL;
705
706   g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
707   g_return_if_fail (buffer != NULL);
708
709   if (count == 0)
710     {
711       simple = g_simple_async_result_new (G_OBJECT (stream),
712                                           callback,
713                                           user_data,
714                                           g_output_stream_write_async);
715       g_simple_async_result_complete_in_idle (simple);
716       g_object_unref (simple);
717       return;
718     }
719
720   if (((gssize) count) < 0)
721     {
722       g_simple_async_report_error_in_idle (G_OBJECT (stream),
723                                            callback,
724                                            user_data,
725                                            G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
726                                            _("Too large count value passed to %s"),
727                                            G_STRFUNC);
728       return;
729     }
730
731   if (!g_output_stream_set_pending (stream, &error))
732     {
733       g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
734                                             callback,
735                                             user_data,
736                                             error);
737       g_error_free (error);
738       return;
739     }
740   
741   class = G_OUTPUT_STREAM_GET_CLASS (stream);
742
743   stream->priv->outstanding_callback = callback;
744   g_object_ref (stream);
745   class->write_async (stream, buffer, count, io_priority, cancellable,
746                       async_ready_callback_wrapper, user_data);
747 }
748
749 /**
750  * g_output_stream_write_finish:
751  * @stream: a #GOutputStream.
752  * @result: a #GAsyncResult.
753  * @error: a #GError location to store the error occuring, or %NULL to 
754  * ignore.
755  * 
756  * Finishes a stream write operation.
757  * 
758  * Returns: a #gssize containing the number of bytes written to the stream.
759  **/
760 gssize
761 g_output_stream_write_finish (GOutputStream  *stream,
762                               GAsyncResult   *result,
763                               GError        **error)
764 {
765   GSimpleAsyncResult *simple;
766   GOutputStreamClass *class;
767
768   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), -1);
769   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), -1);
770
771   if (G_IS_SIMPLE_ASYNC_RESULT (result))
772     {
773       simple = G_SIMPLE_ASYNC_RESULT (result);
774       if (g_simple_async_result_propagate_error (simple, error))
775         return -1;
776
777       /* Special case writes of 0 bytes */
778       if (g_simple_async_result_get_source_tag (simple) == g_output_stream_write_async)
779         return 0;
780     }
781   
782   class = G_OUTPUT_STREAM_GET_CLASS (stream);
783   return class->write_finish (stream, result, error);
784 }
785
786 typedef struct {
787   GInputStream *source;
788   gpointer user_data;
789   GAsyncReadyCallback callback;
790 } SpliceUserData;
791
792 static void
793 async_ready_splice_callback_wrapper (GObject      *source_object,
794                                      GAsyncResult *res,
795                                      gpointer     _data)
796 {
797   GOutputStream *stream = G_OUTPUT_STREAM (source_object);
798   SpliceUserData *data = _data;
799   
800   g_output_stream_clear_pending (stream);
801   
802   if (data->callback)
803     (*data->callback) (source_object, res, data->user_data);
804   
805   g_object_unref (stream);
806   g_object_unref (data->source);
807   g_free (data);
808 }
809
810 /**
811  * g_output_stream_splice_async:
812  * @stream: a #GOutputStream.
813  * @source: a #GInputStream. 
814  * @flags: a set of #GOutputStreamSpliceFlags.
815  * @io_priority: the io priority of the request.
816  * @cancellable: optional #GCancellable object, %NULL to ignore. 
817  * @callback: a #GAsyncReadyCallback. 
818  * @user_data: user data passed to @callback.
819  * 
820  * Splices a stream asynchronously.
821  * When the operation is finished @callback will be called.
822  * You can then call g_output_stream_splice_finish() to get the 
823  * result of the operation.
824  *
825  * For the synchronous, blocking version of this function, see 
826  * g_output_stream_splice().
827  **/
828 void
829 g_output_stream_splice_async (GOutputStream            *stream,
830                               GInputStream             *source,
831                               GOutputStreamSpliceFlags  flags,
832                               int                       io_priority,
833                               GCancellable             *cancellable,
834                               GAsyncReadyCallback       callback,
835                               gpointer                  user_data)
836 {
837   GOutputStreamClass *class;
838   SpliceUserData *data;
839   GError *error = NULL;
840
841   g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
842   g_return_if_fail (G_IS_INPUT_STREAM (source));
843
844   if (g_input_stream_is_closed (source))
845     {
846       g_simple_async_report_error_in_idle (G_OBJECT (stream),
847                                            callback,
848                                            user_data,
849                                            G_IO_ERROR, G_IO_ERROR_CLOSED,
850                                            _("Source stream is already closed"));
851       return;
852     }
853   
854   if (!g_output_stream_set_pending (stream, &error))
855     {
856       g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
857                                             callback,
858                                             user_data,
859                                             error);
860       g_error_free (error);
861       return;
862     }
863
864   class = G_OUTPUT_STREAM_GET_CLASS (stream);
865
866   data = g_new0 (SpliceUserData, 1);
867   data->callback = callback;
868   data->user_data = user_data;
869   data->source = g_object_ref (source);
870   
871   g_object_ref (stream);
872   class->splice_async (stream, source, flags, io_priority, cancellable,
873                       async_ready_splice_callback_wrapper, data);
874 }
875
876 /**
877  * g_output_stream_splice_finish:
878  * @stream: a #GOutputStream.
879  * @result: a #GAsyncResult.
880  * @error: a #GError location to store the error occuring, or %NULL to 
881  * ignore.
882  *
883  * Finishes an asynchronous stream splice operation.
884  * 
885  * Returns: a #gssize of the number of bytes spliced.
886  **/
887 gssize
888 g_output_stream_splice_finish (GOutputStream  *stream,
889                                GAsyncResult   *result,
890                                GError        **error)
891 {
892   GSimpleAsyncResult *simple;
893   GOutputStreamClass *class;
894
895   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), -1);
896   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), -1);
897
898   if (G_IS_SIMPLE_ASYNC_RESULT (result))
899     {
900       simple = G_SIMPLE_ASYNC_RESULT (result);
901       if (g_simple_async_result_propagate_error (simple, error))
902         return -1;
903     }
904   
905   class = G_OUTPUT_STREAM_GET_CLASS (stream);
906   return class->splice_finish (stream, result, error);
907 }
908
909 /**
910  * g_output_stream_flush_async:
911  * @stream: a #GOutputStream.
912  * @io_priority: the io priority of the request.
913  * @cancellable: optional #GCancellable object, %NULL to ignore.
914  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
915  * @user_data: the data to pass to callback function
916  * 
917  * Flushes a stream asynchronously.
918  * For behaviour details see g_output_stream_flush().
919  *
920  * When the operation is finished @callback will be 
921  * called. You can then call g_output_stream_flush_finish() to get the 
922  * result of the operation.
923  **/
924 void
925 g_output_stream_flush_async (GOutputStream       *stream,
926                              int                  io_priority,
927                              GCancellable        *cancellable,
928                              GAsyncReadyCallback  callback,
929                              gpointer             user_data)
930 {
931   GOutputStreamClass *class;
932   GSimpleAsyncResult *simple;
933   GError *error = NULL;
934
935   g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
936
937   if (!g_output_stream_set_pending (stream, &error))
938     {
939       g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
940                                             callback,
941                                             user_data,
942                                             error);
943       g_error_free (error);
944       return;
945     }
946
947   stream->priv->outstanding_callback = callback;
948   g_object_ref (stream);
949
950   class = G_OUTPUT_STREAM_GET_CLASS (stream);
951   
952   if (class->flush_async == NULL)
953     {
954       simple = g_simple_async_result_new (G_OBJECT (stream),
955                                           async_ready_callback_wrapper,
956                                           user_data,
957                                           g_output_stream_flush_async);
958       g_simple_async_result_complete_in_idle (simple);
959       g_object_unref (simple);
960       return;
961     }
962       
963   class->flush_async (stream, io_priority, cancellable,
964                       async_ready_callback_wrapper, user_data);
965 }
966
967 /**
968  * g_output_stream_flush_finish:
969  * @stream: a #GOutputStream.
970  * @result: a GAsyncResult.
971  * @error: a #GError location to store the error occuring, or %NULL to 
972  * ignore.
973  * 
974  * Finishes flushing an output stream.
975  * 
976  * Returns: %TRUE if flush operation suceeded, %FALSE otherwise.
977  **/
978 gboolean
979 g_output_stream_flush_finish (GOutputStream  *stream,
980                               GAsyncResult   *result,
981                               GError        **error)
982 {
983   GSimpleAsyncResult *simple;
984   GOutputStreamClass *klass;
985
986   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
987   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
988
989   if (G_IS_SIMPLE_ASYNC_RESULT (result))
990     {
991       simple = G_SIMPLE_ASYNC_RESULT (result);
992       if (g_simple_async_result_propagate_error (simple, error))
993         return FALSE;
994
995       /* Special case default implementation */
996       if (g_simple_async_result_get_source_tag (simple) == g_output_stream_flush_async)
997         return TRUE;
998     }
999
1000   klass = G_OUTPUT_STREAM_GET_CLASS (stream);
1001   return klass->flush_finish (stream, result, error);
1002 }
1003
1004
1005 /**
1006  * g_output_stream_close_async:
1007  * @stream: A #GOutputStream.
1008  * @io_priority: the io priority of the request.
1009  * @callback: callback to call when the request is satisfied
1010  * @user_data: the data to pass to callback function
1011  * @cancellable: optional cancellable object
1012  *
1013  * Requests an asynchronous close of the stream, releasing resources 
1014  * related to it. When the operation is finished @callback will be 
1015  * called. You can then call g_output_stream_close_finish() to get 
1016  * the result of the operation.
1017  *
1018  * For behaviour details see g_output_stream_close().
1019  *
1020  * The asyncronous methods have a default fallback that uses threads 
1021  * to implement asynchronicity, so they are optional for inheriting 
1022  * classes. However, if you override one you must override all.
1023  **/
1024 void
1025 g_output_stream_close_async (GOutputStream       *stream,
1026                              int                  io_priority,
1027                              GCancellable        *cancellable,
1028                              GAsyncReadyCallback  callback,
1029                              gpointer             user_data)
1030 {
1031   GOutputStreamClass *class;
1032   GSimpleAsyncResult *simple;
1033   GError *error = NULL;
1034   CloseUserData *data;
1035
1036   g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
1037   
1038   if (stream->priv->closed)
1039     {
1040       simple = g_simple_async_result_new (G_OBJECT (stream),
1041                                           callback,
1042                                           user_data,
1043                                           g_output_stream_close_async);
1044       g_simple_async_result_complete_in_idle (simple);
1045       g_object_unref (simple);
1046       return;
1047     }
1048
1049   if (!g_output_stream_set_pending (stream, &error))
1050     {
1051       g_simple_async_report_gerror_in_idle (G_OBJECT (stream),
1052                                             callback,
1053                                             user_data,
1054                                             error);
1055       g_error_free (error);
1056       return;
1057     }
1058   
1059   class = G_OUTPUT_STREAM_GET_CLASS (stream);
1060   stream->priv->closing = TRUE;
1061   stream->priv->outstanding_callback = callback;
1062   g_object_ref (stream);
1063
1064   data = g_slice_new0 (CloseUserData);
1065
1066   if (cancellable != NULL)
1067     data->cancellable = g_object_ref (cancellable);
1068
1069   data->io_priority = io_priority;
1070   data->user_data = user_data;
1071
1072   /* Call close_async directly if there is no need to flush, or if the flush
1073      can be done sync (in the output stream async close thread) */
1074   if (class->flush_async == NULL ||
1075       (class->flush_async == g_output_stream_real_flush_async &&
1076        (class->flush == NULL || class->close_async == g_output_stream_real_close_async)))
1077     {
1078       class->close_async (stream, io_priority, cancellable,
1079                           async_ready_close_callback_wrapper, data);
1080     }
1081   else
1082     {
1083       /* First do an async flush, then do the async close in the callback
1084          wrapper (see async_ready_close_flushed_callback_wrapper) */
1085       class->flush_async (stream, io_priority, cancellable,
1086                           async_ready_close_flushed_callback_wrapper, data);
1087     }
1088 }
1089
1090 /**
1091  * g_output_stream_close_finish:
1092  * @stream: a #GOutputStream.
1093  * @result: a #GAsyncResult.
1094  * @error: a #GError location to store the error occuring, or %NULL to 
1095  * ignore.
1096  * 
1097  * Closes an output stream.
1098  * 
1099  * Returns: %TRUE if stream was successfully closed, %FALSE otherwise.
1100  **/
1101 gboolean
1102 g_output_stream_close_finish (GOutputStream  *stream,
1103                               GAsyncResult   *result,
1104                               GError        **error)
1105 {
1106   GSimpleAsyncResult *simple;
1107   GOutputStreamClass *class;
1108
1109   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
1110   g_return_val_if_fail (G_IS_ASYNC_RESULT (result), FALSE);
1111
1112   if (G_IS_SIMPLE_ASYNC_RESULT (result))
1113     {
1114       simple = G_SIMPLE_ASYNC_RESULT (result);
1115       if (g_simple_async_result_propagate_error (simple, error))
1116         return FALSE;
1117
1118       /* Special case already closed */
1119       if (g_simple_async_result_get_source_tag (simple) == g_output_stream_close_async)
1120         return TRUE;
1121     }
1122
1123   class = G_OUTPUT_STREAM_GET_CLASS (stream);
1124   return class->close_finish (stream, result, error);
1125 }
1126
1127 /**
1128  * g_output_stream_is_closed:
1129  * @stream: a #GOutputStream.
1130  * 
1131  * Checks if an output stream has already been closed.
1132  * 
1133  * Returns: %TRUE if @stream is closed. %FALSE otherwise. 
1134  **/
1135 gboolean
1136 g_output_stream_is_closed (GOutputStream *stream)
1137 {
1138   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), TRUE);
1139   
1140   return stream->priv->closed;
1141 }
1142
1143 /**
1144  * g_output_stream_is_closing:
1145  * @stream: a #GOutputStream.
1146  *
1147  * Checks if an output stream is being closed. This can be
1148  * used inside e.g. a flush implementation to see if the
1149  * flush (or other i/o operation) is called from within
1150  * the closing operation.
1151  *
1152  * Returns: %TRUE if @stream is being closed. %FALSE otherwise.
1153  *
1154  * Since: 2.24
1155  **/
1156 gboolean
1157 g_output_stream_is_closing (GOutputStream *stream)
1158 {
1159   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), TRUE);
1160
1161   return stream->priv->closing;
1162 }
1163
1164 /**
1165  * g_output_stream_has_pending:
1166  * @stream: a #GOutputStream.
1167  * 
1168  * Checks if an ouput stream has pending actions.
1169  * 
1170  * Returns: %TRUE if @stream has pending actions. 
1171  **/
1172 gboolean
1173 g_output_stream_has_pending (GOutputStream *stream)
1174 {
1175   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
1176   
1177   return stream->priv->pending;
1178 }
1179
1180 /**
1181  * g_output_stream_set_pending:
1182  * @stream: a #GOutputStream.
1183  * @error: a #GError location to store the error occuring, or %NULL to 
1184  * ignore.
1185  * 
1186  * Sets @stream to have actions pending. If the pending flag is
1187  * already set or @stream is closed, it will return %FALSE and set
1188  * @error.
1189  *
1190  * Return value: %TRUE if pending was previously unset and is now set.
1191  **/
1192 gboolean
1193 g_output_stream_set_pending (GOutputStream *stream,
1194                              GError **error)
1195 {
1196   g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
1197   
1198   if (stream->priv->closed)
1199     {
1200       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CLOSED,
1201                            _("Stream is already closed"));
1202       return FALSE;
1203     }
1204   
1205   if (stream->priv->pending)
1206     {
1207       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PENDING,
1208                            /* Translators: This is an error you get if there is
1209                             * already an operation running against this stream when
1210                             * you try to start one */
1211                            _("Stream has outstanding operation"));
1212       return FALSE;
1213     }
1214   
1215   stream->priv->pending = TRUE;
1216   return TRUE;
1217 }
1218
1219 /**
1220  * g_output_stream_clear_pending:
1221  * @stream: output stream
1222  * 
1223  * Clears the pending flag on @stream.
1224  **/
1225 void
1226 g_output_stream_clear_pending (GOutputStream *stream)
1227 {
1228   g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
1229   
1230   stream->priv->pending = FALSE;
1231 }
1232
1233
1234 /********************************************
1235  *   Default implementation of async ops    *
1236  ********************************************/
1237
1238 typedef struct {
1239   const void         *buffer;
1240   gsize               count_requested;
1241   gssize              count_written;
1242 } WriteData;
1243
1244 static void
1245 write_async_thread (GSimpleAsyncResult *res,
1246                     GObject            *object,
1247                     GCancellable       *cancellable)
1248 {
1249   WriteData *op;
1250   GOutputStreamClass *class;
1251   GError *error = NULL;
1252
1253   class = G_OUTPUT_STREAM_GET_CLASS (object);
1254   op = g_simple_async_result_get_op_res_gpointer (res);
1255   op->count_written = class->write_fn (G_OUTPUT_STREAM (object), op->buffer, op->count_requested,
1256                                        cancellable, &error);
1257   if (op->count_written == -1)
1258     g_simple_async_result_take_error (res, error);
1259 }
1260
1261 static void
1262 g_output_stream_real_write_async (GOutputStream       *stream,
1263                                   const void          *buffer,
1264                                   gsize                count,
1265                                   int                  io_priority,
1266                                   GCancellable        *cancellable,
1267                                   GAsyncReadyCallback  callback,
1268                                   gpointer             user_data)
1269 {
1270   GSimpleAsyncResult *res;
1271   WriteData *op;
1272
1273   op = g_new0 (WriteData, 1);
1274   res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_write_async);
1275   g_simple_async_result_set_op_res_gpointer (res, op, g_free);
1276   op->buffer = buffer;
1277   op->count_requested = count;
1278   
1279   g_simple_async_result_run_in_thread (res, write_async_thread, io_priority, cancellable);
1280   g_object_unref (res);
1281 }
1282
1283 static gssize
1284 g_output_stream_real_write_finish (GOutputStream  *stream,
1285                                    GAsyncResult   *result,
1286                                    GError        **error)
1287 {
1288   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
1289   WriteData *op;
1290
1291   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_output_stream_real_write_async);
1292   op = g_simple_async_result_get_op_res_gpointer (simple);
1293   return op->count_written;
1294 }
1295
1296 typedef struct {
1297   GInputStream *source;
1298   GOutputStreamSpliceFlags flags;
1299   gssize bytes_copied;
1300 } SpliceData;
1301
1302 static void
1303 splice_async_thread (GSimpleAsyncResult *result,
1304                      GObject            *object,
1305                      GCancellable       *cancellable)
1306 {
1307   SpliceData *op;
1308   GOutputStreamClass *class;
1309   GError *error = NULL;
1310   GOutputStream *stream;
1311
1312   stream = G_OUTPUT_STREAM (object);
1313   class = G_OUTPUT_STREAM_GET_CLASS (object);
1314   op = g_simple_async_result_get_op_res_gpointer (result);
1315   
1316   op->bytes_copied = class->splice (stream,
1317                                     op->source,
1318                                     op->flags,
1319                                     cancellable,
1320                                     &error);
1321   if (op->bytes_copied == -1)
1322     g_simple_async_result_take_error (result, error);
1323 }
1324
1325 static void
1326 g_output_stream_real_splice_async (GOutputStream             *stream,
1327                                    GInputStream              *source,
1328                                    GOutputStreamSpliceFlags   flags,
1329                                    int                        io_priority,
1330                                    GCancellable              *cancellable,
1331                                    GAsyncReadyCallback        callback,
1332                                    gpointer                   user_data)
1333 {
1334   GSimpleAsyncResult *res;
1335   SpliceData *op;
1336
1337   op = g_new0 (SpliceData, 1);
1338   res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_splice_async);
1339   g_simple_async_result_set_op_res_gpointer (res, op, g_free);
1340   op->flags = flags;
1341   op->source = source;
1342
1343   /* TODO: In the case where both source and destintion have
1344      non-threadbased async calls we can use a true async copy here */
1345   
1346   g_simple_async_result_run_in_thread (res, splice_async_thread, io_priority, cancellable);
1347   g_object_unref (res);
1348 }
1349
1350 static gssize
1351 g_output_stream_real_splice_finish (GOutputStream  *stream,
1352                                     GAsyncResult   *result,
1353                                     GError        **error)
1354 {
1355   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
1356   SpliceData *op;
1357
1358   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_output_stream_real_splice_async);
1359   op = g_simple_async_result_get_op_res_gpointer (simple);
1360   return op->bytes_copied;
1361 }
1362
1363
1364 static void
1365 flush_async_thread (GSimpleAsyncResult *res,
1366                     GObject            *object,
1367                     GCancellable       *cancellable)
1368 {
1369   GOutputStreamClass *class;
1370   gboolean result;
1371   GError *error = NULL;
1372
1373   class = G_OUTPUT_STREAM_GET_CLASS (object);
1374   result = TRUE;
1375   if (class->flush)
1376     result = class->flush (G_OUTPUT_STREAM (object), cancellable, &error);
1377
1378   if (!result)
1379     g_simple_async_result_take_error (res, error);
1380 }
1381
1382 static void
1383 g_output_stream_real_flush_async (GOutputStream       *stream,
1384                                   int                  io_priority,
1385                                   GCancellable        *cancellable,
1386                                   GAsyncReadyCallback  callback,
1387                                   gpointer             user_data)
1388 {
1389   GSimpleAsyncResult *res;
1390
1391   res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_write_async);
1392   
1393   g_simple_async_result_run_in_thread (res, flush_async_thread, io_priority, cancellable);
1394   g_object_unref (res);
1395 }
1396
1397 static gboolean
1398 g_output_stream_real_flush_finish (GOutputStream  *stream,
1399                                    GAsyncResult   *result,
1400                                    GError        **error)
1401 {
1402   return TRUE;
1403 }
1404
1405 static void
1406 close_async_thread (GSimpleAsyncResult *res,
1407                     GObject            *object,
1408                     GCancellable       *cancellable)
1409 {
1410   GOutputStreamClass *class;
1411   GError *error = NULL;
1412   gboolean result = TRUE;
1413
1414   class = G_OUTPUT_STREAM_GET_CLASS (object);
1415
1416   /* Do a flush here if there is a flush function, and we did not have to do
1417      an async flush before (see g_output_stream_close_async) */
1418   if (class->flush != NULL &&
1419       (class->flush_async == NULL ||
1420        class->flush_async == g_output_stream_real_flush_async))
1421     {
1422       result = class->flush (G_OUTPUT_STREAM (object), cancellable, &error);
1423     }
1424
1425   /* Auto handling of cancelation disabled, and ignore
1426      cancellation, since we want to close things anyway, although
1427      possibly in a quick-n-dirty way. At least we never want to leak
1428      open handles */
1429   
1430   if (class->close_fn)
1431     {
1432       /* Make sure to close, even if the flush failed (see sync close) */
1433       if (!result)
1434         class->close_fn (G_OUTPUT_STREAM (object), cancellable, NULL);
1435       else
1436         result = class->close_fn (G_OUTPUT_STREAM (object), cancellable, &error);
1437
1438       if (!result)
1439         g_simple_async_result_take_error (res, error);
1440     }
1441 }
1442
1443 static void
1444 g_output_stream_real_close_async (GOutputStream       *stream,
1445                                   int                  io_priority,
1446                                   GCancellable        *cancellable,
1447                                   GAsyncReadyCallback  callback,
1448                                   gpointer             user_data)
1449 {
1450   GSimpleAsyncResult *res;
1451   
1452   res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_output_stream_real_close_async);
1453
1454   g_simple_async_result_set_handle_cancellation (res, FALSE);
1455   
1456   g_simple_async_result_run_in_thread (res, close_async_thread, io_priority, cancellable);
1457   g_object_unref (res);
1458 }
1459
1460 static gboolean
1461 g_output_stream_real_close_finish (GOutputStream  *stream,
1462                                    GAsyncResult   *result,
1463                                    GError        **error)
1464 {
1465   GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
1466   g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_output_stream_real_close_async);
1467   return TRUE;
1468 }