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