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