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