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