X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgoutputstream.c;h=2bec89e7e591ab6079f7b081727ae83c3192205a;hb=2e5bd8cf47f9e1559ccc44823a2f321b8ff8c1ea;hp=125c41819440fdbc64ca39346066408e625e2731;hpb=078dbda148a81af1b3a76fbda72f089b963087f1;p=platform%2Fupstream%2Fglib.git diff --git a/gio/goutputstream.c b/gio/goutputstream.c index 125c418..2bec89e 100644 --- a/gio/goutputstream.c +++ b/gio/goutputstream.c @@ -176,7 +176,7 @@ g_output_stream_init (GOutputStream *stream) * * Virtual: write_fn * - * Return value: Number of bytes written, or -1 on error + * Returns: Number of bytes written, or -1 on error **/ gssize g_output_stream_write (GOutputStream *stream, @@ -246,10 +246,17 @@ g_output_stream_write (GOutputStream *stream, * is set to @count. * * If there is an error during the operation %FALSE is returned and @error - * is set to indicate the error status, @bytes_written is updated to contain - * the number of bytes written into the stream before the error occurred. + * is set to indicate the error status. + * + * As a special exception to the normal conventions for functions that + * use #GError, if this function returns %FALSE (and sets @error) then + * @bytes_written will be set to the number of bytes that were + * successfully written before the error was encountered. This + * functionality is only available from C. If you need it from another + * language then you must write your own loop around + * g_output_stream_write(). * - * Return value: %TRUE on success, %FALSE if there was an error + * Returns: %TRUE on success, %FALSE if there was an error **/ gboolean g_output_stream_write_all (GOutputStream *stream, @@ -314,7 +321,7 @@ g_output_stream_write_all (GOutputStream *stream, * * Since: 2.40 * - * Return value: %TRUE on success, %FALSE if there was an error + * Returns: %TRUE on success, %FALSE if there was an error **/ gboolean g_output_stream_printf (GOutputStream *stream, @@ -360,7 +367,7 @@ g_output_stream_printf (GOutputStream *stream, * * Since: 2.40 * - * Return value: %TRUE on success, %FALSE if there was an error + * Returns: %TRUE on success, %FALSE if there was an error **/ gboolean g_output_stream_vprintf (GOutputStream *stream, @@ -399,15 +406,14 @@ g_output_stream_vprintf (GOutputStream *stream, * bindings or in other cases where the refcounted nature of #GBytes * is helpful over a bare pointer interface. * - * However, note that this function may still - * perform partial writes, just like g_output_stream_write(). If that - * occurs, to continue writing, you will need to create a new #GBytes - * containing just the remaining bytes, using - * g_bytes_new_from_bytes(). Passing the same #GBytes instance - * multiple times potentially can result in duplicated data in the - * output stream. + * However, note that this function may still perform partial writes, + * just like g_output_stream_write(). If that occurs, to continue + * writing, you will need to create a new #GBytes containing just the + * remaining bytes, using g_bytes_new_from_bytes(). Passing the same + * #GBytes instance multiple times potentially can result in duplicated + * data in the output stream. * - * Return value: Number of bytes written, or -1 on error + * Returns: Number of bytes written, or -1 on error **/ gssize g_output_stream_write_bytes (GOutputStream *stream, @@ -442,7 +448,7 @@ g_output_stream_write_bytes (GOutputStream *stream, * triggering the cancellable object from another thread. If the operation * was cancelled, the error %G_IO_ERROR_CANCELLED will be returned. * - * Return value: %TRUE on success, %FALSE on error + * Returns: %TRUE on success, %FALSE on error **/ gboolean g_output_stream_flush (GOutputStream *stream, @@ -693,7 +699,7 @@ g_output_stream_internal_close (GOutputStream *stream, * cancellation (as with any error) there is no guarantee that all written * data will reach the target. * - * Return value: %TRUE on success, %FALSE on failure + * Returns: %TRUE on success, %FALSE on failure **/ gboolean g_output_stream_close (GOutputStream *stream, @@ -786,11 +792,11 @@ async_ready_write_callback_wrapper (GObject *source_object, * For the synchronous, blocking version of this function, see * g_output_stream_write(). * - * No copy of @buffer will be made, so it must stay valid until - * @callback is called. See g_output_stream_write_bytes_async() for a #GBytes - * version that will automatically hold a reference to the contents (without - * copying) for the duration of the call. - **/ + * Note that no copy of @buffer will be made, so it must stay valid + * until @callback is called. See g_output_stream_write_bytes_async() + * for a #GBytes version that will automatically hold a reference to + * the contents (without copying) for the duration of the call. + */ void g_output_stream_write_async (GOutputStream *stream, const void *buffer, @@ -866,6 +872,189 @@ g_output_stream_write_finish (GOutputStream *stream, return g_task_propagate_int (G_TASK (result), error); } +typedef struct +{ + const guint8 *buffer; + gsize to_write; + gsize bytes_written; +} AsyncWriteAll; + +static void +free_async_write_all (gpointer data) +{ + g_slice_free (AsyncWriteAll, data); +} + +static void +write_all_callback (GObject *stream, + GAsyncResult *result, + gpointer user_data) +{ + GTask *task = user_data; + AsyncWriteAll *data = g_task_get_task_data (task); + + if (result) + { + GError *error = NULL; + gssize nwritten; + + nwritten = g_output_stream_write_finish (G_OUTPUT_STREAM (stream), result, &error); + + if (nwritten == -1) + { + g_task_return_error (task, error); + g_object_unref (task); + return; + } + + g_assert_cmpint (nwritten, <=, data->to_write); + g_warn_if_fail (nwritten > 0); + + data->to_write -= nwritten; + data->bytes_written += nwritten; + } + + if (data->to_write == 0) + { + g_task_return_boolean (task, TRUE); + g_object_unref (task); + } + + else + g_output_stream_write_async (G_OUTPUT_STREAM (stream), + data->buffer + data->bytes_written, + data->to_write, + g_task_get_priority (task), + g_task_get_cancellable (task), + write_all_callback, task); +} + +static void +write_all_async_thread (GTask *task, + gpointer source_object, + gpointer task_data, + GCancellable *cancellable) +{ + GOutputStream *stream = source_object; + AsyncWriteAll *data = task_data; + GError *error = NULL; + + if (g_output_stream_write_all (stream, data->buffer, data->to_write, &data->bytes_written, + g_task_get_cancellable (task), &error)) + g_task_return_boolean (task, TRUE); + else + g_task_return_error (task, error); +} + +/** + * g_output_stream_write_all_async: + * @stream: A #GOutputStream + * @buffer: (array length=count) (element-type guint8): the buffer containing the data to write + * @count: the number of bytes to write + * @io_priority: the io priority of the request + * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore + * @callback: (scope async): callback to call when the request is satisfied + * @user_data: (closure): the data to pass to callback function + * + * Request an asynchronous write of @count bytes from @buffer into + * the stream. When the operation is finished @callback will be called. + * You can then call g_output_stream_write_all_finish() to get the result of the + * operation. + * + * This is the asynchronous version of g_output_stream_write_all(). + * + * Call g_output_stream_write_all_finish() to collect the result. + * + * Any outstanding I/O request with higher priority (lower numerical + * value) will be executed before an outstanding request with lower + * priority. Default priority is %G_PRIORITY_DEFAULT. + * + * Note that no copy of @buffer will be made, so it must stay valid + * until @callback is called. + * + * Since: 2.44 + */ +void +g_output_stream_write_all_async (GOutputStream *stream, + const void *buffer, + gsize count, + int io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + AsyncWriteAll *data; + GTask *task; + + g_return_if_fail (G_IS_OUTPUT_STREAM (stream)); + g_return_if_fail (buffer != NULL || count == 0); + + task = g_task_new (stream, cancellable, callback, user_data); + data = g_slice_new0 (AsyncWriteAll); + data->buffer = buffer; + data->to_write = count; + + g_task_set_task_data (task, data, free_async_write_all); + g_task_set_priority (task, io_priority); + + /* If async writes are going to be handled via the threadpool anyway + * then we may as well do it with a single dispatch instead of + * bouncing in and out. + */ + if (g_output_stream_async_write_is_via_threads (stream)) + { + g_task_run_in_thread (task, write_all_async_thread); + g_object_unref (task); + } + else + write_all_callback (G_OBJECT (stream), NULL, task); +} + +/** + * g_output_stream_write_all_finish: + * @stream: a #GOutputStream + * @result: a #GAsyncResult + * @bytes_written: (out): location to store the number of bytes that was written to the stream + * @error: a #GError location to store the error occurring, or %NULL to ignore. + * + * Finishes an asynchronous stream write operation started with + * g_output_stream_write_all_async(). + * + * As a special exception to the normal conventions for functions that + * use #GError, if this function returns %FALSE (and sets @error) then + * @bytes_written will be set to the number of bytes that were + * successfully written before the error was encountered. This + * functionality is only available from C. If you need it from another + * language then you must write your own loop around + * g_output_stream_write_async(). + * + * Returns: %TRUE on success, %FALSE if there was an error + * + * Since: 2.44 + **/ +gboolean +g_output_stream_write_all_finish (GOutputStream *stream, + GAsyncResult *result, + gsize *bytes_written, + GError **error) +{ + GTask *task; + + g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE); + g_return_val_if_fail (g_task_is_valid (result, stream), FALSE); + + task = G_TASK (result); + + if (bytes_written) + { + AsyncWriteAll *data = (AsyncWriteAll *)g_task_get_task_data (task); + + *bytes_written = data->bytes_written; + } + + return g_task_propagate_boolean (task, error); +} + static void write_bytes_callback (GObject *stream, GAsyncResult *result, @@ -897,13 +1086,12 @@ write_bytes_callback (GObject *stream, * takes a #GBytes as input. Due to the refcounted nature of #GBytes, * this allows the stream to avoid taking a copy of the data. * - * However, note that this function may still - * perform partial writes, just like g_output_stream_write_async(). - * If that occurs, to continue writing, you will need to create a new - * #GBytes containing just the remaining bytes, using - * g_bytes_new_from_bytes(). Passing the same #GBytes instance - * multiple times potentially can result in duplicated data in the - * output stream. + * However, note that this function may still perform partial writes, + * just like g_output_stream_write_async(). If that occurs, to continue + * writing, you will need to create a new #GBytes containing just the + * remaining bytes, using g_bytes_new_from_bytes(). Passing the same + * #GBytes instance multiple times potentially can result in duplicated + * data in the output stream. * * For the synchronous, blocking version of this function, see * g_output_stream_write_bytes(). @@ -1452,7 +1640,7 @@ g_output_stream_has_pending (GOutputStream *stream) * already set or @stream is closed, it will return %FALSE and set * @error. * - * Return value: %TRUE if pending was previously unset and is now set. + * Returns: %TRUE if pending was previously unset and is now set. **/ gboolean g_output_stream_set_pending (GOutputStream *stream,