gio: port basic I/O classes from GSimpleAsyncResult to GTask

https://bugzilla.gnome.org/show_bug.cgi?id=661767
This commit is contained in:
Dan Winship 2012-08-02 15:49:59 -04:00
parent 586adb9790
commit 669505e354
10 changed files with 770 additions and 1149 deletions

View File

@ -26,7 +26,7 @@
#include "ginputstream.h" #include "ginputstream.h"
#include "gcancellable.h" #include "gcancellable.h"
#include "gasyncresult.h" #include "gasyncresult.h"
#include "gsimpleasyncresult.h" #include "gtask.h"
#include "gseekable.h" #include "gseekable.h"
#include "gioerror.h" #include "gioerror.h"
#include <string.h> #include <string.h>
@ -483,27 +483,25 @@ g_buffered_input_stream_fill_async (GBufferedInputStream *stream,
gpointer user_data) gpointer user_data)
{ {
GBufferedInputStreamClass *class; GBufferedInputStreamClass *class;
GSimpleAsyncResult *simple;
GError *error = NULL; GError *error = NULL;
g_return_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream)); g_return_if_fail (G_IS_BUFFERED_INPUT_STREAM (stream));
if (count == 0) if (count == 0)
{ {
simple = g_simple_async_result_new (G_OBJECT (stream), GTask *task;
callback,
user_data, task = g_task_new (stream, cancellable, callback, user_data);
g_buffered_input_stream_fill_async); g_task_set_source_tag (task, g_buffered_input_stream_fill_async);
g_simple_async_result_complete_in_idle (simple); g_task_return_int (task, 0);
g_object_unref (simple); g_object_unref (task);
return; return;
} }
if (count < -1) if (count < -1)
{ {
g_simple_async_report_error_in_idle (G_OBJECT (stream), g_task_report_new_error (stream, callback, user_data,
callback, g_buffered_input_stream_fill_async,
user_data,
G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
_("Too large count value passed to %s"), _("Too large count value passed to %s"),
G_STRFUNC); G_STRFUNC);
@ -512,9 +510,8 @@ g_buffered_input_stream_fill_async (GBufferedInputStream *stream,
if (!g_input_stream_set_pending (G_INPUT_STREAM (stream), &error)) if (!g_input_stream_set_pending (G_INPUT_STREAM (stream), &error))
{ {
g_simple_async_report_take_gerror_in_idle (G_OBJECT (stream), g_task_report_error (stream, callback, user_data,
callback, g_buffered_input_stream_fill_async,
user_data,
error); error);
return; return;
} }
@ -550,10 +547,7 @@ g_buffered_input_stream_fill_finish (GBufferedInputStream *stream,
if (g_async_result_legacy_propagate_error (result, error)) if (g_async_result_legacy_propagate_error (result, error))
return -1; return -1;
else if (g_async_result_is_tagged (result, g_buffered_input_stream_fill_async)) else if (g_async_result_is_tagged (result, g_buffered_input_stream_fill_async))
{ return g_task_propagate_int (G_TASK (result), error);
/* Special case read of 0 bytes */
return 0;
}
class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream);
return class->fill_finish (stream, result, error); return class->fill_finish (stream, result, error);
@ -1041,38 +1035,28 @@ fill_async_callback (GObject *source_object,
{ {
GError *error; GError *error;
gssize res; gssize res;
GSimpleAsyncResult *simple; GTask *task = user_data;
simple = user_data;
error = NULL; error = NULL;
res = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res = g_input_stream_read_finish (G_INPUT_STREAM (source_object),
result, &error); result, &error);
g_simple_async_result_set_op_res_gssize (simple, res);
if (res == -1) if (res == -1)
{ g_task_return_error (task, error);
g_simple_async_result_take_error (simple, error);
}
else else
{ {
GBufferedInputStream *stream;
GBufferedInputStreamPrivate *priv; GBufferedInputStreamPrivate *priv;
GObject *object;
object = g_async_result_get_source_object (G_ASYNC_RESULT (simple)); stream = g_task_get_source_object (task);
priv = G_BUFFERED_INPUT_STREAM (object)->priv; priv = G_BUFFERED_INPUT_STREAM (stream)->priv;
g_assert_cmpint (priv->end + res, <=, priv->len); g_assert_cmpint (priv->end + res, <=, priv->len);
priv->end += res; priv->end += res;
g_object_unref (object); g_task_return_int (task, res);
} }
/* Complete immediately, not in idle, since we're already g_object_unref (task);
* in a mainloop callout
*/
g_simple_async_result_complete (simple);
g_object_unref (simple);
} }
static void static void
@ -1085,7 +1069,7 @@ g_buffered_input_stream_real_fill_async (GBufferedInputStream *stream,
{ {
GBufferedInputStreamPrivate *priv; GBufferedInputStreamPrivate *priv;
GInputStream *base_stream; GInputStream *base_stream;
GSimpleAsyncResult *simple; GTask *task;
gsize in_buffer; gsize in_buffer;
priv = stream->priv; priv = stream->priv;
@ -1102,9 +1086,7 @@ g_buffered_input_stream_real_fill_async (GBufferedInputStream *stream,
if (priv->len - priv->end < count) if (priv->len - priv->end < count)
compact_buffer (stream); compact_buffer (stream);
simple = g_simple_async_result_new (G_OBJECT (stream), task = g_task_new (stream, cancellable, callback, user_data);
callback, user_data,
g_buffered_input_stream_real_fill_async);
base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream; base_stream = G_FILTER_INPUT_STREAM (stream)->base_stream;
g_input_stream_read_async (base_stream, g_input_stream_read_async (base_stream,
@ -1113,7 +1095,7 @@ g_buffered_input_stream_real_fill_async (GBufferedInputStream *stream,
io_priority, io_priority,
cancellable, cancellable,
fill_async_callback, fill_async_callback,
simple); task);
} }
static gssize static gssize
@ -1121,17 +1103,9 @@ g_buffered_input_stream_real_fill_finish (GBufferedInputStream *stream,
GAsyncResult *result, GAsyncResult *result,
GError **error) GError **error)
{ {
GSimpleAsyncResult *simple; g_return_val_if_fail (g_task_is_valid (result, stream), -1);
gssize nread;
simple = G_SIMPLE_ASYNC_RESULT (result); return g_task_propagate_int (G_TASK (result), error);
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_buffered_input_stream_real_fill_async);
if (g_simple_async_result_propagate_error (simple, error))
return -1;
nread = g_simple_async_result_get_op_res_gssize (simple);
return nread;
} }
typedef struct typedef struct
@ -1152,12 +1126,12 @@ large_skip_callback (GObject *source_object,
GAsyncResult *result, GAsyncResult *result,
gpointer user_data) gpointer user_data)
{ {
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); GTask *task = G_TASK (user_data);
SkipAsyncData *data; SkipAsyncData *data;
GError *error; GError *error;
gssize nread; gssize nread;
data = g_simple_async_result_get_op_res_gpointer (simple); data = g_task_get_task_data (task);
error = NULL; error = NULL;
nread = g_input_stream_skip_finish (G_INPUT_STREAM (source_object), nread = g_input_stream_skip_finish (G_INPUT_STREAM (source_object),
@ -1165,18 +1139,19 @@ large_skip_callback (GObject *source_object,
/* Only report the error if we've not already read some data */ /* Only report the error if we've not already read some data */
if (nread < 0 && data->bytes_skipped == 0) if (nread < 0 && data->bytes_skipped == 0)
g_simple_async_result_take_error (simple, error); g_task_return_error (task, error);
else if (error) else
{
if (error)
g_error_free (error); g_error_free (error);
if (nread > 0) if (nread > 0)
data->bytes_skipped += nread; data->bytes_skipped += nread;
/* Complete immediately, not in idle, since we're already g_task_return_int (task, data->bytes_skipped);
* in a mainloop callout }
*/
g_simple_async_result_complete (simple); g_object_unref (task);
g_object_unref (simple);
} }
static void static void
@ -1184,7 +1159,7 @@ skip_fill_buffer_callback (GObject *source_object,
GAsyncResult *result, GAsyncResult *result,
gpointer user_data) gpointer user_data)
{ {
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); GTask *task = G_TASK (user_data);
GBufferedInputStream *bstream; GBufferedInputStream *bstream;
GBufferedInputStreamPrivate *priv; GBufferedInputStreamPrivate *priv;
SkipAsyncData *data; SkipAsyncData *data;
@ -1195,15 +1170,17 @@ skip_fill_buffer_callback (GObject *source_object,
bstream = G_BUFFERED_INPUT_STREAM (source_object); bstream = G_BUFFERED_INPUT_STREAM (source_object);
priv = bstream->priv; priv = bstream->priv;
data = g_simple_async_result_get_op_res_gpointer (simple); data = g_task_get_task_data (task);
error = NULL; error = NULL;
nread = g_buffered_input_stream_fill_finish (bstream, nread = g_buffered_input_stream_fill_finish (bstream,
result, &error); result, &error);
if (nread < 0 && data->bytes_skipped == 0) if (nread < 0 && data->bytes_skipped == 0)
g_simple_async_result_take_error (simple, error); g_task_return_error (task, error);
else if (error) else
{
if (error)
g_error_free (error); g_error_free (error);
if (nread > 0) if (nread > 0)
@ -1215,11 +1192,10 @@ skip_fill_buffer_callback (GObject *source_object,
priv->pos += data->count; priv->pos += data->count;
} }
/* Complete immediately, not in idle, since we're already g_task_return_int (task, data->bytes_skipped);
* in a mainloop callout }
*/
g_simple_async_result_complete (simple); g_object_unref (task);
g_object_unref (simple);
} }
static void static void
@ -1235,7 +1211,7 @@ g_buffered_input_stream_skip_async (GInputStream *stream,
GBufferedInputStreamClass *class; GBufferedInputStreamClass *class;
GInputStream *base_stream; GInputStream *base_stream;
gsize available; gsize available;
GSimpleAsyncResult *simple; GTask *task;
SkipAsyncData *data; SkipAsyncData *data;
bstream = G_BUFFERED_INPUT_STREAM (stream); bstream = G_BUFFERED_INPUT_STREAM (stream);
@ -1243,20 +1219,17 @@ g_buffered_input_stream_skip_async (GInputStream *stream,
data = g_slice_new (SkipAsyncData); data = g_slice_new (SkipAsyncData);
data->bytes_skipped = 0; data->bytes_skipped = 0;
simple = g_simple_async_result_new (G_OBJECT (stream), task = g_task_new (stream, cancellable, callback, user_data);
callback, user_data, g_task_set_task_data (task, data, free_skip_async_data);
g_buffered_input_stream_skip_async);
g_simple_async_result_set_op_res_gpointer (simple, data, free_skip_async_data);
available = priv->end - priv->pos; available = priv->end - priv->pos;
if (count <= available) if (count <= available)
{ {
priv->pos += count; priv->pos += count;
data->bytes_skipped = count;
g_simple_async_result_complete_in_idle (simple); g_task_return_int (task, count);
g_object_unref (simple); g_object_unref (task);
return; return;
} }
@ -1282,13 +1255,13 @@ g_buffered_input_stream_skip_async (GInputStream *stream,
count, count,
io_priority, cancellable, io_priority, cancellable,
large_skip_callback, large_skip_callback,
simple); task);
} }
else else
{ {
class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream); class = G_BUFFERED_INPUT_STREAM_GET_CLASS (stream);
class->fill_async (bstream, priv->len, io_priority, cancellable, class->fill_async (bstream, priv->len, io_priority, cancellable,
skip_fill_buffer_callback, simple); skip_fill_buffer_callback, task);
} }
} }
@ -1297,14 +1270,7 @@ g_buffered_input_stream_skip_finish (GInputStream *stream,
GAsyncResult *result, GAsyncResult *result,
GError **error) GError **error)
{ {
GSimpleAsyncResult *simple; g_return_val_if_fail (g_task_is_valid (result, stream), -1);
SkipAsyncData *data;
simple = G_SIMPLE_ASYNC_RESULT (result); return g_task_propagate_int (G_TASK (result), error);
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_buffered_input_stream_skip_async);
data = g_simple_async_result_get_op_res_gpointer (simple);
return data->bytes_skipped;
} }

View File

@ -24,7 +24,7 @@
#include "gbufferedoutputstream.h" #include "gbufferedoutputstream.h"
#include "goutputstream.h" #include "goutputstream.h"
#include "gseekable.h" #include "gseekable.h"
#include "gsimpleasyncresult.h" #include "gtask.h"
#include "string.h" #include "string.h"
#include "gioerror.h" #include "gioerror.h"
#include "glibintl.h" #include "glibintl.h"
@ -652,8 +652,9 @@ free_flush_data (gpointer data)
* and so closing and writing is just a special * and so closing and writing is just a special
* case of flushing + some addition stuff */ * case of flushing + some addition stuff */
static void static void
flush_buffer_thread (GSimpleAsyncResult *result, flush_buffer_thread (GTask *task,
GObject *object, gpointer object,
gpointer task_data,
GCancellable *cancellable) GCancellable *cancellable)
{ {
GBufferedOutputStream *stream; GBufferedOutputStream *stream;
@ -663,7 +664,7 @@ flush_buffer_thread (GSimpleAsyncResult *result,
GError *error = NULL; GError *error = NULL;
stream = G_BUFFERED_OUTPUT_STREAM (object); stream = G_BUFFERED_OUTPUT_STREAM (object);
fdata = g_simple_async_result_get_op_res_gpointer (result); fdata = task_data;
base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream; base_stream = G_FILTER_OUTPUT_STREAM (stream)->base_stream;
res = flush_buffer (stream, cancellable, &error); res = flush_buffer (stream, cancellable, &error);
@ -689,7 +690,9 @@ flush_buffer_thread (GSimpleAsyncResult *result,
} }
if (res == FALSE) if (res == FALSE)
g_simple_async_result_take_error (result, error); g_task_return_error (task, error);
else
g_task_return_boolean (task, TRUE);
} }
static void static void
@ -699,25 +702,19 @@ g_buffered_output_stream_flush_async (GOutputStream *stream,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer data) gpointer data)
{ {
GSimpleAsyncResult *res; GTask *task;
FlushData *fdata; FlushData *fdata;
fdata = g_slice_new (FlushData); fdata = g_slice_new (FlushData);
fdata->flush_stream = TRUE; fdata->flush_stream = TRUE;
fdata->close_stream = FALSE; fdata->close_stream = FALSE;
res = g_simple_async_result_new (G_OBJECT (stream), task = g_task_new (stream, cancellable, callback, data);
callback, g_task_set_task_data (task, fdata, free_flush_data);
data, g_task_set_priority (task, io_priority);
g_buffered_output_stream_flush_async);
g_simple_async_result_set_op_res_gpointer (res, fdata, free_flush_data); g_task_run_in_thread (task, flush_buffer_thread);
g_object_unref (task);
g_simple_async_result_run_in_thread (res,
flush_buffer_thread,
io_priority,
cancellable);
g_object_unref (res);
} }
static gboolean static gboolean
@ -725,14 +722,9 @@ g_buffered_output_stream_flush_finish (GOutputStream *stream,
GAsyncResult *result, GAsyncResult *result,
GError **error) GError **error)
{ {
GSimpleAsyncResult *simple; g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
simple = G_SIMPLE_ASYNC_RESULT (result); return g_task_propagate_boolean (G_TASK (result), error);
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) ==
g_buffered_output_stream_flush_async);
return TRUE;
} }
static void static void
@ -742,24 +734,18 @@ g_buffered_output_stream_close_async (GOutputStream *stream,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer data) gpointer data)
{ {
GSimpleAsyncResult *res; GTask *task;
FlushData *fdata; FlushData *fdata;
fdata = g_slice_new (FlushData); fdata = g_slice_new (FlushData);
fdata->close_stream = TRUE; fdata->close_stream = TRUE;
res = g_simple_async_result_new (G_OBJECT (stream), task = g_task_new (stream, cancellable, callback, data);
callback, g_task_set_task_data (task, fdata, free_flush_data);
data, g_task_set_priority (task, io_priority);
g_buffered_output_stream_close_async);
g_simple_async_result_set_op_res_gpointer (res, fdata, free_flush_data); g_task_run_in_thread (task, flush_buffer_thread);
g_object_unref (task);
g_simple_async_result_run_in_thread (res,
flush_buffer_thread,
io_priority,
cancellable);
g_object_unref (res);
} }
static gboolean static gboolean
@ -767,12 +753,7 @@ g_buffered_output_stream_close_finish (GOutputStream *stream,
GAsyncResult *result, GAsyncResult *result,
GError **error) GError **error)
{ {
GSimpleAsyncResult *simple; g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
simple = G_SIMPLE_ASYNC_RESULT (result); return g_task_propagate_boolean (G_TASK (result), error);
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) ==
g_buffered_output_stream_close_async);
return TRUE;
} }

View File

@ -24,7 +24,7 @@
#include "config.h" #include "config.h"
#include "gdatainputstream.h" #include "gdatainputstream.h"
#include "gsimpleasyncresult.h" #include "gtask.h"
#include "gcancellable.h" #include "gcancellable.h"
#include "gioenumtypes.h" #include "gioenumtypes.h"
#include "gioerror.h" #include "gioerror.h"
@ -952,49 +952,41 @@ g_data_input_stream_read_until (GDataInputStream *stream,
typedef struct typedef struct
{ {
GDataInputStream *stream;
GSimpleAsyncResult *simple;
gboolean last_saw_cr; gboolean last_saw_cr;
gsize checked; gsize checked;
gint io_priority;
GCancellable *cancellable;
gchar *stop_chars; gchar *stop_chars;
gssize stop_chars_len; gssize stop_chars_len;
gchar *line;
gsize length; gsize length;
} GDataInputStreamReadData; } GDataInputStreamReadData;
static void static void
g_data_input_stream_read_complete (GDataInputStreamReadData *data, g_data_input_stream_read_complete (GTask *task,
gsize read_length, gsize read_length,
gsize skip_length, gsize skip_length)
gboolean need_idle_dispatch)
{ {
GDataInputStreamReadData *data = g_task_get_task_data (task);
GInputStream *stream = g_task_get_source_object (task);
char *line = NULL;
if (read_length || skip_length) if (read_length || skip_length)
{ {
gssize bytes; gssize bytes;
data->length = read_length; data->length = read_length;
data->line = g_malloc (read_length + 1); line = g_malloc (read_length + 1);
data->line[read_length] = '\0'; line[read_length] = '\0';
/* we already checked the buffer. this shouldn't fail. */ /* we already checked the buffer. this shouldn't fail. */
bytes = g_input_stream_read (G_INPUT_STREAM (data->stream), bytes = g_input_stream_read (stream, line, read_length, NULL, NULL);
data->line, read_length, NULL, NULL);
g_assert_cmpint (bytes, ==, read_length); g_assert_cmpint (bytes, ==, read_length);
bytes = g_input_stream_skip (G_INPUT_STREAM (data->stream), bytes = g_input_stream_skip (stream, skip_length, NULL, NULL);
skip_length, NULL, NULL);
g_assert_cmpint (bytes, ==, skip_length); g_assert_cmpint (bytes, ==, skip_length);
} }
if (need_idle_dispatch) g_task_return_pointer (task, line, g_free);
g_simple_async_result_complete_in_idle (data->simple); g_object_unref (task);
else
g_simple_async_result_complete (data->simple);
g_object_unref (data->simple);
} }
static void static void
@ -1002,14 +994,15 @@ g_data_input_stream_read_line_ready (GObject *object,
GAsyncResult *result, GAsyncResult *result,
gpointer user_data) gpointer user_data)
{ {
GDataInputStreamReadData *data = user_data; GTask *task = user_data;
GDataInputStreamReadData *data = g_task_get_task_data (task);
GBufferedInputStream *buffer = g_task_get_source_object (task);
gssize found_pos; gssize found_pos;
gint newline_len; gint newline_len;
if (result) if (result)
/* this is a callback. finish the async call. */ /* this is a callback. finish the async call. */
{ {
GBufferedInputStream *buffer = G_BUFFERED_INPUT_STREAM (data->stream);
GError *error = NULL; GError *error = NULL;
gssize bytes; gssize bytes;
@ -1020,11 +1013,12 @@ g_data_input_stream_read_line_ready (GObject *object,
if (bytes < 0) if (bytes < 0)
/* stream error. */ /* stream error. */
{ {
g_simple_async_result_take_error (data->simple, error); g_task_return_error (task, error);
data->checked = 0; g_object_unref (task);
return;
} }
g_data_input_stream_read_complete (data, data->checked, 0, FALSE); g_data_input_stream_read_complete (task, data->checked, 0);
return; return;
} }
@ -1033,20 +1027,19 @@ g_data_input_stream_read_line_ready (GObject *object,
if (data->stop_chars) if (data->stop_chars)
{ {
found_pos = scan_for_chars (data->stream, found_pos = scan_for_chars (G_DATA_INPUT_STREAM (buffer),
&data->checked, &data->checked,
data->stop_chars, data->stop_chars,
data->stop_chars_len); data->stop_chars_len);
newline_len = 0; newline_len = 0;
} }
else else
found_pos = scan_for_newline (data->stream, &data->checked, found_pos = scan_for_newline (G_DATA_INPUT_STREAM (buffer), &data->checked,
&data->last_saw_cr, &newline_len); &data->last_saw_cr, &newline_len);
if (found_pos == -1) if (found_pos == -1)
/* didn't find a full line; need to buffer some more bytes */ /* didn't find a full line; need to buffer some more bytes */
{ {
GBufferedInputStream *buffer = G_BUFFERED_INPUT_STREAM (data->stream);
gsize size; gsize size;
size = g_buffered_input_stream_get_buffer_size (buffer); size = g_buffered_input_stream_get_buffer_size (buffer);
@ -1056,16 +1049,16 @@ g_data_input_stream_read_line_ready (GObject *object,
g_buffered_input_stream_set_buffer_size (buffer, size * 2); g_buffered_input_stream_set_buffer_size (buffer, size * 2);
/* try again */ /* try again */
g_buffered_input_stream_fill_async (buffer, -1, data->io_priority, g_buffered_input_stream_fill_async (buffer, -1,
data->cancellable, g_task_get_priority (task),
g_task_get_cancellable (task),
g_data_input_stream_read_line_ready, g_data_input_stream_read_line_ready,
user_data); user_data);
} }
else else
{ {
/* read the line and the EOL. no error is possible. */ /* read the line and the EOL. no error is possible. */
g_data_input_stream_read_complete (data, found_pos, g_data_input_stream_read_complete (task, found_pos, newline_len);
newline_len, result == NULL);
} }
} }
@ -1074,14 +1067,7 @@ g_data_input_stream_read_data_free (gpointer user_data)
{ {
GDataInputStreamReadData *data = user_data; GDataInputStreamReadData *data = user_data;
/* we don't hold a ref to ->simple because it keeps a ref to us.
* we are called because it is being finalized.
*/
g_free (data->stop_chars); g_free (data->stop_chars);
if (data->cancellable)
g_object_unref (data->cancellable);
g_free (data->line);
g_slice_free (GDataInputStreamReadData, data); g_slice_free (GDataInputStreamReadData, data);
} }
@ -1092,30 +1078,23 @@ g_data_input_stream_read_async (GDataInputStream *stream,
gint io_priority, gint io_priority,
GCancellable *cancellable, GCancellable *cancellable,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data, gpointer user_data)
gpointer source_tag)
{ {
GDataInputStreamReadData *data; GDataInputStreamReadData *data;
GTask *task;
data = g_slice_new (GDataInputStreamReadData); data = g_slice_new0 (GDataInputStreamReadData);
data->stream = stream;
if (cancellable)
g_object_ref (cancellable);
data->cancellable = cancellable;
if (stop_chars_len == -1) if (stop_chars_len == -1)
stop_chars_len = strlen (stop_chars); stop_chars_len = strlen (stop_chars);
data->stop_chars = g_memdup (stop_chars, stop_chars_len); data->stop_chars = g_memdup (stop_chars, stop_chars_len);
data->stop_chars_len = stop_chars_len; data->stop_chars_len = stop_chars_len;
data->io_priority = io_priority;
data->last_saw_cr = FALSE; data->last_saw_cr = FALSE;
data->checked = 0;
data->line = NULL;
data->simple = g_simple_async_result_new (G_OBJECT (stream), callback, task = g_task_new (stream, cancellable, callback, user_data);
user_data, source_tag); g_task_set_task_data (task, data, g_data_input_stream_read_data_free);
g_simple_async_result_set_op_res_gpointer (data->simple, data, g_task_set_priority (task, io_priority);
g_data_input_stream_read_data_free);
g_data_input_stream_read_line_ready (NULL, NULL, data); g_data_input_stream_read_line_ready (NULL, NULL, task);
} }
static gchar * static gchar *
@ -1124,22 +1103,17 @@ g_data_input_stream_read_finish (GDataInputStream *stream,
gsize *length, gsize *length,
GError **error) GError **error)
{ {
GDataInputStreamReadData *data; GTask *task = G_TASK (result);
GSimpleAsyncResult *simple;
gchar *line; gchar *line;
simple = G_SIMPLE_ASYNC_RESULT (result); line = g_task_propagate_pointer (task, error);
if (g_simple_async_result_propagate_error (simple, error))
return NULL;
data = g_simple_async_result_get_op_res_gpointer (simple);
line = data->line;
data->line = NULL;
if (length && line) if (length && line)
{
GDataInputStreamReadData *data = g_task_get_task_data (task);
*length = data->length; *length = data->length;
}
return line; return line;
} }
@ -1173,8 +1147,7 @@ g_data_input_stream_read_line_async (GDataInputStream *stream,
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
g_data_input_stream_read_async (stream, NULL, 0, io_priority, g_data_input_stream_read_async (stream, NULL, 0, io_priority,
cancellable, callback, user_data, cancellable, callback, user_data);
g_data_input_stream_read_line_async);
} }
/** /**
@ -1218,8 +1191,7 @@ g_data_input_stream_read_until_async (GDataInputStream *stream,
g_return_if_fail (stop_chars != NULL); g_return_if_fail (stop_chars != NULL);
g_data_input_stream_read_async (stream, stop_chars, -1, io_priority, g_data_input_stream_read_async (stream, stop_chars, -1, io_priority,
cancellable, callback, user_data, cancellable, callback, user_data);
g_data_input_stream_read_until_async);
} }
/** /**
@ -1249,9 +1221,7 @@ g_data_input_stream_read_line_finish (GDataInputStream *stream,
gsize *length, gsize *length,
GError **error) GError **error)
{ {
g_return_val_if_fail ( g_return_val_if_fail (g_task_is_valid (result, stream), NULL);
g_simple_async_result_is_valid (result, G_OBJECT (stream),
g_data_input_stream_read_line_async), NULL);
return g_data_input_stream_read_finish (stream, result, length, error); return g_data_input_stream_read_finish (stream, result, length, error);
} }
@ -1321,9 +1291,7 @@ g_data_input_stream_read_until_finish (GDataInputStream *stream,
gsize *length, gsize *length,
GError **error) GError **error)
{ {
g_return_val_if_fail ( g_return_val_if_fail (g_task_is_valid (result, stream), NULL);
g_simple_async_result_is_valid (result, G_OBJECT (stream),
g_data_input_stream_read_until_async), NULL);
return g_data_input_stream_read_finish (stream, result, length, error); return g_data_input_stream_read_finish (stream, result, length, error);
} }
@ -1463,8 +1431,7 @@ g_data_input_stream_read_upto_async (GDataInputStream *stream,
g_return_if_fail (stop_chars != NULL); g_return_if_fail (stop_chars != NULL);
g_data_input_stream_read_async (stream, stop_chars, stop_chars_len, io_priority, g_data_input_stream_read_async (stream, stop_chars, stop_chars_len, io_priority,
cancellable, callback, user_data, cancellable, callback, user_data);
g_data_input_stream_read_upto_async);
} }
/** /**
@ -1494,9 +1461,7 @@ g_data_input_stream_read_upto_finish (GDataInputStream *stream,
gsize *length, gsize *length,
GError **error) GError **error)
{ {
g_return_val_if_fail ( g_return_val_if_fail (g_task_is_valid (result, stream), NULL);
g_simple_async_result_is_valid (result, G_OBJECT (stream),
g_data_input_stream_read_upto_async), NULL);
return g_data_input_stream_read_finish (stream, result, length, error); return g_data_input_stream_read_finish (stream, result, length, error);
} }

View File

@ -28,7 +28,6 @@
#include "gseekable.h" #include "gseekable.h"
#include "gcancellable.h" #include "gcancellable.h"
#include "gasyncresult.h" #include "gasyncresult.h"
#include "gsimpleasyncresult.h"
#include "gioerror.h" #include "gioerror.h"
#include "gpollableinputstream.h" #include "gpollableinputstream.h"
@ -589,7 +588,6 @@ g_input_stream_read_async (GInputStream *stream,
gpointer user_data) gpointer user_data)
{ {
GInputStreamClass *class; GInputStreamClass *class;
GSimpleAsyncResult *simple;
GError *error = NULL; GError *error = NULL;
g_return_if_fail (G_IS_INPUT_STREAM (stream)); g_return_if_fail (G_IS_INPUT_STREAM (stream));
@ -597,20 +595,19 @@ g_input_stream_read_async (GInputStream *stream,
if (count == 0) if (count == 0)
{ {
simple = g_simple_async_result_new (G_OBJECT (stream), GTask *task;
callback,
user_data, task = g_task_new (stream, cancellable, callback, user_data);
g_input_stream_read_async); g_task_set_source_tag (task, g_input_stream_read_async);
g_simple_async_result_complete_in_idle (simple); g_task_return_int (task, 0);
g_object_unref (simple); g_object_unref (task);
return; return;
} }
if (((gssize) count) < 0) if (((gssize) count) < 0)
{ {
g_simple_async_report_error_in_idle (G_OBJECT (stream), g_task_report_new_error (stream, callback, user_data,
callback, g_input_stream_read_async,
user_data,
G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
_("Too large count value passed to %s"), _("Too large count value passed to %s"),
G_STRFUNC); G_STRFUNC);
@ -619,9 +616,8 @@ g_input_stream_read_async (GInputStream *stream,
if (!g_input_stream_set_pending (stream, &error)) if (!g_input_stream_set_pending (stream, &error))
{ {
g_simple_async_report_take_gerror_in_idle (G_OBJECT (stream), g_task_report_error (stream, callback, user_data,
callback, g_input_stream_read_async,
user_data,
error); error);
return; return;
} }
@ -657,10 +653,7 @@ g_input_stream_read_finish (GInputStream *stream,
if (g_async_result_legacy_propagate_error (result, error)) if (g_async_result_legacy_propagate_error (result, error))
return -1; return -1;
else if (g_async_result_is_tagged (result, g_input_stream_read_async)) else if (g_async_result_is_tagged (result, g_input_stream_read_async))
{ return g_task_propagate_int (G_TASK (result), error);
/* Special case read of 0 bytes */
return 0;
}
class = G_INPUT_STREAM_GET_CLASS (stream); class = G_INPUT_STREAM_GET_CLASS (stream);
return class->read_finish (stream, result, error); return class->read_finish (stream, result, error);
@ -671,8 +664,8 @@ read_bytes_callback (GObject *stream,
GAsyncResult *result, GAsyncResult *result,
gpointer user_data) gpointer user_data)
{ {
GSimpleAsyncResult *simple = user_data; GTask *task = user_data;
guchar *buf = g_simple_async_result_get_op_res_gpointer (simple); guchar *buf = g_task_get_task_data (task);
GError *error = NULL; GError *error = NULL;
gssize nread; gssize nread;
GBytes *bytes = NULL; GBytes *bytes = NULL;
@ -682,7 +675,7 @@ read_bytes_callback (GObject *stream,
if (nread == -1) if (nread == -1)
{ {
g_free (buf); g_free (buf);
g_simple_async_result_take_error (simple, error); g_task_return_error (task, error);
} }
else if (nread == 0) else if (nread == 0)
{ {
@ -693,12 +686,9 @@ read_bytes_callback (GObject *stream,
bytes = g_bytes_new_take (buf, nread); bytes = g_bytes_new_take (buf, nread);
if (bytes) if (bytes)
{ g_task_return_pointer (task, bytes, (GDestroyNotify)g_bytes_unref);
g_simple_async_result_set_op_res_gpointer (simple, bytes,
(GDestroyNotify)g_bytes_unref); g_object_unref (task);
}
g_simple_async_result_complete (simple);
g_object_unref (simple);
} }
/** /**
@ -740,18 +730,16 @@ g_input_stream_read_bytes_async (GInputStream *stream,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
GSimpleAsyncResult *simple; GTask *task;
guchar *buf; guchar *buf;
simple = g_simple_async_result_new (G_OBJECT (stream), task = g_task_new (stream, cancellable, callback, user_data);
callback, user_data,
g_input_stream_read_bytes_async);
buf = g_malloc (count); buf = g_malloc (count);
g_simple_async_result_set_op_res_gpointer (simple, buf, NULL); g_task_set_task_data (task, buf, NULL);
g_input_stream_read_async (stream, buf, count, g_input_stream_read_async (stream, buf, count,
io_priority, cancellable, io_priority, cancellable,
read_bytes_callback, simple); read_bytes_callback, task);
} }
/** /**
@ -770,15 +758,10 @@ g_input_stream_read_bytes_finish (GInputStream *stream,
GAsyncResult *result, GAsyncResult *result,
GError **error) GError **error)
{ {
GSimpleAsyncResult *simple;
g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL); g_return_val_if_fail (G_IS_INPUT_STREAM (stream), NULL);
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (stream), g_input_stream_read_bytes_async), NULL); g_return_val_if_fail (g_task_is_valid (result, stream), NULL);
simple = G_SIMPLE_ASYNC_RESULT (result); return g_task_propagate_pointer (G_TASK (result), error);
if (g_simple_async_result_propagate_error (simple, error))
return NULL;
return g_bytes_ref (g_simple_async_result_get_op_res_gpointer (simple));
} }
/** /**
@ -824,28 +807,25 @@ g_input_stream_skip_async (GInputStream *stream,
gpointer user_data) gpointer user_data)
{ {
GInputStreamClass *class; GInputStreamClass *class;
GSimpleAsyncResult *simple;
GError *error = NULL; GError *error = NULL;
g_return_if_fail (G_IS_INPUT_STREAM (stream)); g_return_if_fail (G_IS_INPUT_STREAM (stream));
if (count == 0) if (count == 0)
{ {
simple = g_simple_async_result_new (G_OBJECT (stream), GTask *task;
callback,
user_data,
g_input_stream_skip_async);
g_simple_async_result_complete_in_idle (simple); task = g_task_new (stream, cancellable, callback, user_data);
g_object_unref (simple); g_task_set_source_tag (task, g_input_stream_skip_async);
g_task_return_int (task, 0);
g_object_unref (task);
return; return;
} }
if (((gssize) count) < 0) if (((gssize) count) < 0)
{ {
g_simple_async_report_error_in_idle (G_OBJECT (stream), g_task_report_new_error (stream, callback, user_data,
callback, g_input_stream_skip_async,
user_data,
G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
_("Too large count value passed to %s"), _("Too large count value passed to %s"),
G_STRFUNC); G_STRFUNC);
@ -854,9 +834,8 @@ g_input_stream_skip_async (GInputStream *stream,
if (!g_input_stream_set_pending (stream, &error)) if (!g_input_stream_set_pending (stream, &error))
{ {
g_simple_async_report_take_gerror_in_idle (G_OBJECT (stream), g_task_report_error (stream, callback, user_data,
callback, g_input_stream_skip_async,
user_data,
error); error);
return; return;
} }
@ -892,10 +871,7 @@ g_input_stream_skip_finish (GInputStream *stream,
if (g_async_result_legacy_propagate_error (result, error)) if (g_async_result_legacy_propagate_error (result, error))
return -1; return -1;
else if (g_async_result_is_tagged (result, g_input_stream_skip_async)) else if (g_async_result_is_tagged (result, g_input_stream_skip_async))
{ return g_task_propagate_int (G_TASK (result), error);
/* Special case skip of 0 bytes */
return 0;
}
class = G_INPUT_STREAM_GET_CLASS (stream); class = G_INPUT_STREAM_GET_CLASS (stream);
return class->skip_finish (stream, result, error); return class->skip_finish (stream, result, error);
@ -929,28 +905,25 @@ g_input_stream_close_async (GInputStream *stream,
gpointer user_data) gpointer user_data)
{ {
GInputStreamClass *class; GInputStreamClass *class;
GSimpleAsyncResult *simple;
GError *error = NULL; GError *error = NULL;
g_return_if_fail (G_IS_INPUT_STREAM (stream)); g_return_if_fail (G_IS_INPUT_STREAM (stream));
if (stream->priv->closed) if (stream->priv->closed)
{ {
simple = g_simple_async_result_new (G_OBJECT (stream), GTask *task;
callback,
user_data,
g_input_stream_close_async);
g_simple_async_result_complete_in_idle (simple); task = g_task_new (stream, cancellable, callback, user_data);
g_object_unref (simple); g_task_set_source_tag (task, g_input_stream_close_async);
g_task_return_boolean (task, TRUE);
g_object_unref (task);
return; return;
} }
if (!g_input_stream_set_pending (stream, &error)) if (!g_input_stream_set_pending (stream, &error))
{ {
g_simple_async_report_take_gerror_in_idle (G_OBJECT (stream), g_task_report_error (stream, callback, user_data,
callback, g_input_stream_close_async,
user_data,
error); error);
return; return;
} }
@ -986,10 +959,7 @@ g_input_stream_close_finish (GInputStream *stream,
if (g_async_result_legacy_propagate_error (result, error)) if (g_async_result_legacy_propagate_error (result, error))
return FALSE; return FALSE;
else if (g_async_result_is_tagged (result, g_input_stream_close_async)) else if (g_async_result_is_tagged (result, g_input_stream_close_async))
{ return g_task_propagate_boolean (G_TASK (result), error);
/* Special case already closed */
return TRUE;
}
class = G_INPUT_STREAM_GET_CLASS (stream); class = G_INPUT_STREAM_GET_CLASS (stream);
return class->close_finish (stream, result, error); return class->close_finish (stream, result, error);
@ -1085,94 +1055,85 @@ g_input_stream_clear_pending (GInputStream *stream)
typedef struct { typedef struct {
void *buffer; void *buffer;
gsize count_requested; gsize count;
gssize count_read;
GCancellable *cancellable;
gint io_priority;
gboolean need_idle;
} ReadData; } ReadData;
static void static void
free_read_data (ReadData *op) free_read_data (ReadData *op)
{ {
if (op->cancellable)
g_object_unref (op->cancellable);
g_slice_free (ReadData, op); g_slice_free (ReadData, op);
} }
static void static void
read_async_thread (GSimpleAsyncResult *res, read_async_thread (GTask *task,
GObject *object, gpointer source_object,
gpointer task_data,
GCancellable *cancellable) GCancellable *cancellable)
{ {
ReadData *op; GInputStream *stream = source_object;
ReadData *op = task_data;
GInputStreamClass *class; GInputStreamClass *class;
GError *error = NULL; GError *error = NULL;
gssize nread;
op = g_simple_async_result_get_op_res_gpointer (res); class = G_INPUT_STREAM_GET_CLASS (stream);
class = G_INPUT_STREAM_GET_CLASS (object); nread = class->read_fn (stream,
op->buffer, op->count,
op->count_read = class->read_fn (G_INPUT_STREAM (object), g_task_get_cancellable (task),
op->buffer, op->count_requested, &error);
cancellable, &error); if (nread == -1)
if (op->count_read == -1) g_task_return_error (task, error);
g_simple_async_result_take_error (res, error); else
g_task_return_int (task, nread);
} }
static void read_async_pollable (GPollableInputStream *stream, static void read_async_pollable (GPollableInputStream *stream,
GSimpleAsyncResult *result); GTask *task);
static gboolean static gboolean
read_async_pollable_ready (GPollableInputStream *stream, read_async_pollable_ready (GPollableInputStream *stream,
gpointer user_data) gpointer user_data)
{ {
GSimpleAsyncResult *result = user_data; GTask *task = user_data;
read_async_pollable (stream, result); read_async_pollable (stream, task);
return FALSE; return FALSE;
} }
static void static void
read_async_pollable (GPollableInputStream *stream, read_async_pollable (GPollableInputStream *stream,
GSimpleAsyncResult *result) GTask *task)
{ {
ReadData *op = g_task_get_task_data (task);
GError *error = NULL; GError *error = NULL;
ReadData *op = g_simple_async_result_get_op_res_gpointer (result); gssize nread;
if (g_cancellable_set_error_if_cancelled (op->cancellable, &error)) if (g_task_return_error_if_cancelled (task))
op->count_read = -1; return;
else
{ nread = G_POLLABLE_INPUT_STREAM_GET_INTERFACE (stream)->
op->count_read = G_POLLABLE_INPUT_STREAM_GET_INTERFACE (stream)-> read_nonblocking (stream, op->buffer, op->count, &error);
read_nonblocking (stream, op->buffer, op->count_requested, &error);
}
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
{ {
GSource *source; GSource *source;
g_error_free (error); g_error_free (error);
op->need_idle = FALSE;
source = g_pollable_input_stream_create_source (stream, op->cancellable); source = g_pollable_input_stream_create_source (stream,
g_source_set_callback (source, g_task_get_cancellable (task));
(GSourceFunc) read_async_pollable_ready, g_task_attach_source (task, source,
g_object_ref (result), g_object_unref); (GSourceFunc) read_async_pollable_ready);
g_source_set_priority (source, op->io_priority);
g_source_attach (source, g_main_context_get_thread_default ());
g_source_unref (source); g_source_unref (source);
return; return;
} }
if (op->count_read == -1) if (nread == -1)
g_simple_async_result_take_error (result, error); g_task_return_error (task, error);
if (op->need_idle)
g_simple_async_result_complete_in_idle (result);
else else
g_simple_async_result_complete (result); g_task_return_int (task, nread);
/* g_input_stream_real_read_async() unrefs task */
} }
static void static void
@ -1184,24 +1145,22 @@ g_input_stream_real_read_async (GInputStream *stream,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
GSimpleAsyncResult *res; GTask *task;
ReadData *op; ReadData *op;
op = g_slice_new0 (ReadData); op = g_slice_new0 (ReadData);
res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_input_stream_real_read_async); task = g_task_new (stream, cancellable, callback, user_data);
g_simple_async_result_set_op_res_gpointer (res, op, (GDestroyNotify) free_read_data); g_task_set_task_data (task, op, (GDestroyNotify) free_read_data);
g_task_set_priority (task, io_priority);
op->buffer = buffer; op->buffer = buffer;
op->count_requested = count; op->count = count;
op->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
op->io_priority = io_priority;
op->need_idle = TRUE;
if (G_IS_POLLABLE_INPUT_STREAM (stream) && if (G_IS_POLLABLE_INPUT_STREAM (stream) &&
g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (stream))) g_pollable_input_stream_can_poll (G_POLLABLE_INPUT_STREAM (stream)))
read_async_pollable (G_POLLABLE_INPUT_STREAM (stream), res); read_async_pollable (G_POLLABLE_INPUT_STREAM (stream), task);
else else
g_simple_async_result_run_in_thread (res, read_async_thread, io_priority, cancellable); g_task_run_in_thread (task, read_async_thread);
g_object_unref (res); g_object_unref (task);
} }
static gssize static gssize
@ -1209,50 +1168,38 @@ g_input_stream_real_read_finish (GInputStream *stream,
GAsyncResult *result, GAsyncResult *result,
GError **error) GError **error)
{ {
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); g_return_val_if_fail (g_task_is_valid (result, stream), -1);
ReadData *op;
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == return g_task_propagate_int (G_TASK (result), error);
g_input_stream_real_read_async);
if (g_simple_async_result_propagate_error (simple, error))
return -1;
op = g_simple_async_result_get_op_res_gpointer (simple);
return op->count_read;
} }
typedef struct {
gsize count_requested;
gssize count_skipped;
} SkipData;
static void static void
skip_async_thread (GSimpleAsyncResult *res, skip_async_thread (GTask *task,
GObject *object, gpointer source_object,
gpointer task_data,
GCancellable *cancellable) GCancellable *cancellable)
{ {
SkipData *op; GInputStream *stream = source_object;
gsize count = GPOINTER_TO_SIZE (task_data);
GInputStreamClass *class; GInputStreamClass *class;
GError *error = NULL; GError *error = NULL;
gssize ret;
class = G_INPUT_STREAM_GET_CLASS (object); class = G_INPUT_STREAM_GET_CLASS (stream);
op = g_simple_async_result_get_op_res_gpointer (res); ret = class->skip (stream, count,
op->count_skipped = class->skip (G_INPUT_STREAM (object), g_task_get_cancellable (task),
op->count_requested, &error);
cancellable, &error); if (ret == -1)
if (op->count_skipped == -1) g_task_return_error (task, error);
g_simple_async_result_take_error (res, error); else
g_task_return_int (task, ret);
} }
typedef struct { typedef struct {
char buffer[8192]; char buffer[8192];
gsize count; gsize count;
gsize count_skipped; gsize count_skipped;
int io_prio;
GCancellable *cancellable;
gpointer user_data; gpointer user_data;
GAsyncReadyCallback callback; GAsyncReadyCallback callback;
} SkipFallbackAsyncData; } SkipFallbackAsyncData;
@ -1263,9 +1210,8 @@ skip_callback_wrapper (GObject *source_object,
gpointer user_data) gpointer user_data)
{ {
GInputStreamClass *class; GInputStreamClass *class;
SkipFallbackAsyncData *data = user_data; GTask *task = user_data;
SkipData *op; SkipFallbackAsyncData *data = g_task_get_task_data (task);
GSimpleAsyncResult *simple;
GError *error = NULL; GError *error = NULL;
gssize ret; gssize ret;
@ -1279,35 +1225,28 @@ skip_callback_wrapper (GObject *source_object,
if (data->count > 0) if (data->count > 0)
{ {
class = G_INPUT_STREAM_GET_CLASS (source_object); class = G_INPUT_STREAM_GET_CLASS (source_object);
class->read_async (G_INPUT_STREAM (source_object), data->buffer, MIN (8192, data->count), data->io_prio, data->cancellable, class->read_async (G_INPUT_STREAM (source_object),
data->buffer, MIN (8192, data->count),
g_task_get_priority (task),
g_task_get_cancellable (task),
skip_callback_wrapper, data); skip_callback_wrapper, data);
return; return;
} }
} }
op = g_new0 (SkipData, 1); if (ret == -1 &&
op->count_skipped = data->count_skipped; g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
simple = g_simple_async_result_new (source_object, data->count_skipped)
data->callback, data->user_data,
g_input_stream_real_skip_async);
g_simple_async_result_set_op_res_gpointer (simple, op, g_free);
if (ret == -1)
{ {
if (data->count_skipped &&
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
/* No error, return partial read */ /* No error, return partial read */
g_error_free (error); g_clear_error (&error);
else
g_simple_async_result_take_error (simple, error);
} }
/* Complete immediately, not in idle, since we're already in a mainloop callout */ if (error)
g_simple_async_result_complete (simple); g_task_return_error (task, error);
g_object_unref (simple); else
g_task_return_int (task, data->count_skipped);
g_free (data); g_object_unref (task);
} }
static void static void
@ -1319,28 +1258,23 @@ g_input_stream_real_skip_async (GInputStream *stream,
gpointer user_data) gpointer user_data)
{ {
GInputStreamClass *class; GInputStreamClass *class;
SkipData *op;
SkipFallbackAsyncData *data; SkipFallbackAsyncData *data;
GSimpleAsyncResult *res; GTask *task;
class = G_INPUT_STREAM_GET_CLASS (stream); class = G_INPUT_STREAM_GET_CLASS (stream);
task = g_task_new (stream, cancellable, callback, user_data);
g_task_set_priority (task, io_priority);
if (class->read_async == g_input_stream_real_read_async) if (class->read_async == g_input_stream_real_read_async)
{ {
/* Read is thread-using async fallback. /* Read is thread-using async fallback.
* Make skip use threads too, so that we can use a possible sync skip * Make skip use threads too, so that we can use a possible sync skip
* implementation. */ * implementation. */
op = g_new0 (SkipData, 1); g_task_set_task_data (task, GSIZE_TO_POINTER (count), NULL);
res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data, g_task_run_in_thread (task, skip_async_thread);
g_input_stream_real_skip_async); g_object_unref (task);
g_simple_async_result_set_op_res_gpointer (res, op, g_free);
op->count_requested = count;
g_simple_async_result_run_in_thread (res, skip_async_thread, io_priority, cancellable);
g_object_unref (res);
} }
else else
{ {
@ -1350,10 +1284,10 @@ g_input_stream_real_skip_async (GInputStream *stream,
data = g_new (SkipFallbackAsyncData, 1); data = g_new (SkipFallbackAsyncData, 1);
data->count = count; data->count = count;
data->count_skipped = 0; data->count_skipped = 0;
data->io_prio = io_priority;
data->cancellable = cancellable;
data->callback = callback; data->callback = callback;
data->user_data = user_data; data->user_data = user_data;
g_task_set_task_data (task, data, g_free);
g_task_set_check_cancellable (task, FALSE);
class->read_async (stream, data->buffer, MIN (8192, count), io_priority, cancellable, class->read_async (stream, data->buffer, MIN (8192, count), io_priority, cancellable,
skip_callback_wrapper, data); skip_callback_wrapper, data);
} }
@ -1365,41 +1299,38 @@ g_input_stream_real_skip_finish (GInputStream *stream,
GAsyncResult *result, GAsyncResult *result,
GError **error) GError **error)
{ {
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); g_return_val_if_fail (g_task_is_valid (result, stream), -1);
SkipData *op;
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_input_stream_real_skip_async); return g_task_propagate_int (G_TASK (result), error);
if (g_simple_async_result_propagate_error (simple, error))
return -1;
op = g_simple_async_result_get_op_res_gpointer (simple);
return op->count_skipped;
} }
static void static void
close_async_thread (GSimpleAsyncResult *res, close_async_thread (GTask *task,
GObject *object, gpointer source_object,
gpointer task_data,
GCancellable *cancellable) GCancellable *cancellable)
{ {
GInputStream *stream = source_object;
GInputStreamClass *class; GInputStreamClass *class;
GError *error = NULL; GError *error = NULL;
gboolean result; gboolean result;
/* Auto handling of cancelation disabled, and ignore class = G_INPUT_STREAM_GET_CLASS (stream);
cancellation, since we want to close things anyway, although
possibly in a quick-n-dirty way. At least we never want to leak
open handles */
class = G_INPUT_STREAM_GET_CLASS (object);
if (class->close_fn) if (class->close_fn)
{ {
result = class->close_fn (G_INPUT_STREAM (object), cancellable, &error); result = class->close_fn (stream,
g_task_get_cancellable (task),
&error);
if (!result) if (!result)
g_simple_async_result_take_error (res, error); {
g_task_return_error (task, error);
return;
} }
} }
g_task_return_boolean (task, TRUE);
}
static void static void
g_input_stream_real_close_async (GInputStream *stream, g_input_stream_real_close_async (GInputStream *stream,
int io_priority, int io_priority,
@ -1407,20 +1338,14 @@ g_input_stream_real_close_async (GInputStream *stream,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
GSimpleAsyncResult *res; GTask *task;
res = g_simple_async_result_new (G_OBJECT (stream), task = g_task_new (stream, cancellable, callback, user_data);
callback, g_task_set_check_cancellable (task, FALSE);
user_data, g_task_set_priority (task, io_priority);
g_input_stream_real_close_async);
g_simple_async_result_set_handle_cancellation (res, FALSE); g_task_run_in_thread (task, close_async_thread);
g_object_unref (task);
g_simple_async_result_run_in_thread (res,
close_async_thread,
io_priority,
cancellable);
g_object_unref (res);
} }
static gboolean static gboolean
@ -1428,12 +1353,7 @@ g_input_stream_real_close_finish (GInputStream *stream,
GAsyncResult *result, GAsyncResult *result,
GError **error) GError **error)
{ {
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_input_stream_real_close_async); return g_task_propagate_boolean (G_TASK (result), error);
if (g_simple_async_result_propagate_error (simple, error))
return FALSE;
return TRUE;
} }

View File

@ -27,9 +27,8 @@
#include "glibintl.h" #include "glibintl.h"
#include "giostream.h" #include "giostream.h"
#include <gio/gsimpleasyncresult.h> #include "gasyncresult.h"
#include <gio/gasyncresult.h> #include "gtask.h"
G_DEFINE_ABSTRACT_TYPE (GIOStream, g_io_stream, G_TYPE_OBJECT); G_DEFINE_ABSTRACT_TYPE (GIOStream, g_io_stream, G_TYPE_OBJECT);
@ -465,27 +464,25 @@ g_io_stream_close_async (GIOStream *stream,
gpointer user_data) gpointer user_data)
{ {
GIOStreamClass *class; GIOStreamClass *class;
GSimpleAsyncResult *simple;
GError *error = NULL; GError *error = NULL;
g_return_if_fail (G_IS_IO_STREAM (stream)); g_return_if_fail (G_IS_IO_STREAM (stream));
if (stream->priv->closed) if (stream->priv->closed)
{ {
simple = g_simple_async_result_new (G_OBJECT (stream), GTask *task;
callback,
user_data, task = g_task_new (stream, cancellable, callback, user_data);
g_io_stream_close_async); g_task_set_source_tag (task, g_io_stream_close_async);
g_simple_async_result_complete_in_idle (simple); g_task_return_boolean (task, TRUE);
g_object_unref (simple); g_object_unref (task);
return; return;
} }
if (!g_io_stream_set_pending (stream, &error)) if (!g_io_stream_set_pending (stream, &error))
{ {
g_simple_async_report_take_gerror_in_idle (G_OBJECT (stream), g_task_report_error (stream, callback, user_data,
callback, g_io_stream_close_async,
user_data,
error); error);
return; return;
} }
@ -523,10 +520,7 @@ g_io_stream_close_finish (GIOStream *stream,
if (g_async_result_legacy_propagate_error (result, error)) if (g_async_result_legacy_propagate_error (result, error))
return FALSE; return FALSE;
else if (g_async_result_is_tagged (result, g_io_stream_close_async)) else if (g_async_result_is_tagged (result, g_io_stream_close_async))
{ return g_task_propagate_boolean (G_TASK (result), error);
/* Special case already closed */
return TRUE;
}
class = G_IO_STREAM_GET_CLASS (stream); class = G_IO_STREAM_GET_CLASS (stream);
return class->close_finish (stream, result, error); return class->close_finish (stream, result, error);
@ -534,27 +528,32 @@ g_io_stream_close_finish (GIOStream *stream,
static void static void
close_async_thread (GSimpleAsyncResult *res, close_async_thread (GTask *task,
GObject *object, gpointer source_object,
gpointer task_data,
GCancellable *cancellable) GCancellable *cancellable)
{ {
GIOStream *stream = source_object;
GIOStreamClass *class; GIOStreamClass *class;
GError *error = NULL; GError *error = NULL;
gboolean result; gboolean result;
/* Auto handling of cancelation disabled, and ignore cancellation, class = G_IO_STREAM_GET_CLASS (stream);
* since we want to close things anyway, although possibly in a
* quick-n-dirty way. At least we never want to leak open handles
*/
class = G_IO_STREAM_GET_CLASS (object);
if (class->close_fn) if (class->close_fn)
{ {
result = class->close_fn (G_IO_STREAM (object), cancellable, &error); result = class->close_fn (stream,
g_task_get_cancellable (task),
&error);
if (!result) if (!result)
g_simple_async_result_take_error (res, error); {
g_task_return_error (task, error);
return;
} }
} }
g_task_return_boolean (task, TRUE);
}
static void static void
g_io_stream_real_close_async (GIOStream *stream, g_io_stream_real_close_async (GIOStream *stream,
int io_priority, int io_priority,
@ -562,20 +561,14 @@ g_io_stream_real_close_async (GIOStream *stream,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
GSimpleAsyncResult *res; GTask *task;
res = g_simple_async_result_new (G_OBJECT (stream), task = g_task_new (stream, cancellable, callback, user_data);
callback, g_task_set_check_cancellable (task, FALSE);
user_data, g_task_set_priority (task, io_priority);
g_io_stream_real_close_async);
g_simple_async_result_set_handle_cancellation (res, FALSE); g_task_run_in_thread (task, close_async_thread);
g_object_unref (task);
g_simple_async_result_run_in_thread (res,
close_async_thread,
io_priority,
cancellable);
g_object_unref (res);
} }
static gboolean static gboolean
@ -583,15 +576,9 @@ g_io_stream_real_close_finish (GIOStream *stream,
GAsyncResult *result, GAsyncResult *result,
GError **error) GError **error)
{ {
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result); g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == return g_task_propagate_boolean (G_TASK (result), error);
g_io_stream_real_close_async);
if (g_simple_async_result_propagate_error (simple, error))
return FALSE;
return TRUE;
} }
typedef struct typedef struct
@ -622,7 +609,7 @@ splice_context_free (SpliceContext *ctx)
} }
static void static void
splice_complete (GSimpleAsyncResult *simple, splice_complete (GTask *task,
SpliceContext *ctx) SpliceContext *ctx)
{ {
if (ctx->cancelled_id != 0) if (ctx->cancelled_id != 0)
@ -630,8 +617,12 @@ splice_complete (GSimpleAsyncResult *simple,
ctx->cancelled_id = 0; ctx->cancelled_id = 0;
if (ctx->error != NULL) if (ctx->error != NULL)
g_simple_async_result_set_from_error (simple, ctx->error); {
g_simple_async_result_complete (simple); g_task_return_error (task, ctx->error);
ctx->error = NULL;
}
else
g_task_return_boolean (task, TRUE);
} }
static void static void
@ -639,13 +630,12 @@ splice_close_cb (GObject *iostream,
GAsyncResult *res, GAsyncResult *res,
gpointer user_data) gpointer user_data)
{ {
GSimpleAsyncResult *simple = user_data; GTask *task = user_data;
SpliceContext *ctx; SpliceContext *ctx = g_task_get_task_data (task);
GError *error = NULL; GError *error = NULL;
g_io_stream_close_finish (G_IO_STREAM (iostream), res, &error); g_io_stream_close_finish (G_IO_STREAM (iostream), res, &error);
ctx = g_simple_async_result_get_op_res_gpointer (simple);
ctx->completed++; ctx->completed++;
/* Keep the first error that occurred */ /* Keep the first error that occurred */
@ -656,9 +646,9 @@ splice_close_cb (GObject *iostream,
/* If all operations are done, complete now */ /* If all operations are done, complete now */
if (ctx->completed == 4) if (ctx->completed == 4)
splice_complete (simple, ctx); splice_complete (task, ctx);
g_object_unref (simple); g_object_unref (task);
} }
static void static void
@ -666,13 +656,12 @@ splice_cb (GObject *ostream,
GAsyncResult *res, GAsyncResult *res,
gpointer user_data) gpointer user_data)
{ {
GSimpleAsyncResult *simple = user_data; GTask *task = user_data;
SpliceContext *ctx; SpliceContext *ctx = g_task_get_task_data (task);
GError *error = NULL; GError *error = NULL;
g_output_stream_splice_finish (G_OUTPUT_STREAM (ostream), res, &error); g_output_stream_splice_finish (G_OUTPUT_STREAM (ostream), res, &error);
ctx = g_simple_async_result_get_op_res_gpointer (simple);
ctx->completed++; ctx->completed++;
/* ignore cancellation error if it was not requested by the user */ /* ignore cancellation error if it was not requested by the user */
@ -706,32 +695,40 @@ splice_cb (GObject *ostream,
/* Close the IO streams if needed */ /* Close the IO streams if needed */
if ((ctx->flags & G_IO_STREAM_SPLICE_CLOSE_STREAM1) != 0) if ((ctx->flags & G_IO_STREAM_SPLICE_CLOSE_STREAM1) != 0)
g_io_stream_close_async (ctx->stream1, ctx->io_priority, {
ctx->op1_cancellable, splice_close_cb, g_object_ref (simple)); g_io_stream_close_async (ctx->stream1,
g_task_get_priority (task),
ctx->op1_cancellable,
splice_close_cb, g_object_ref (task));
}
else else
ctx->completed++; ctx->completed++;
if ((ctx->flags & G_IO_STREAM_SPLICE_CLOSE_STREAM2) != 0) if ((ctx->flags & G_IO_STREAM_SPLICE_CLOSE_STREAM2) != 0)
g_io_stream_close_async (ctx->stream2, ctx->io_priority, {
ctx->op2_cancellable, splice_close_cb, g_object_ref (simple)); g_io_stream_close_async (ctx->stream2,
g_task_get_priority (task),
ctx->op2_cancellable,
splice_close_cb, g_object_ref (task));
}
else else
ctx->completed++; ctx->completed++;
/* If all operations are done, complete now */ /* If all operations are done, complete now */
if (ctx->completed == 4) if (ctx->completed == 4)
splice_complete (simple, ctx); splice_complete (task, ctx);
} }
g_object_unref (simple); g_object_unref (task);
} }
static void static void
splice_cancelled_cb (GCancellable *cancellable, splice_cancelled_cb (GCancellable *cancellable,
GSimpleAsyncResult *simple) GTask *task)
{ {
SpliceContext *ctx; SpliceContext *ctx;
ctx = g_simple_async_result_get_op_res_gpointer (simple); ctx = g_task_get_task_data (task);
g_cancellable_cancel (ctx->op1_cancellable); g_cancellable_cancel (ctx->op1_cancellable);
g_cancellable_cancel (ctx->op2_cancellable); g_cancellable_cancel (ctx->op2_cancellable);
} }
@ -765,15 +762,16 @@ g_io_stream_splice_async (GIOStream *stream1,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
GSimpleAsyncResult *simple; GTask *task;
SpliceContext *ctx; SpliceContext *ctx;
GInputStream *istream; GInputStream *istream;
GOutputStream *ostream; GOutputStream *ostream;
if (cancellable != NULL && g_cancellable_is_cancelled (cancellable)) if (cancellable != NULL && g_cancellable_is_cancelled (cancellable))
{ {
g_simple_async_report_error_in_idle (NULL, callback, g_task_report_new_error (NULL, callback, user_data,
user_data, G_IO_ERROR, G_IO_ERROR_CANCELLED, g_io_stream_splice_async,
G_IO_ERROR, G_IO_ERROR_CANCELLED,
"Operation has been cancelled"); "Operation has been cancelled");
return; return;
} }
@ -782,21 +780,18 @@ g_io_stream_splice_async (GIOStream *stream1,
ctx->stream1 = g_object_ref (stream1); ctx->stream1 = g_object_ref (stream1);
ctx->stream2 = g_object_ref (stream2); ctx->stream2 = g_object_ref (stream2);
ctx->flags = flags; ctx->flags = flags;
ctx->io_priority = io_priority;
ctx->op1_cancellable = g_cancellable_new (); ctx->op1_cancellable = g_cancellable_new ();
ctx->op2_cancellable = g_cancellable_new (); ctx->op2_cancellable = g_cancellable_new ();
ctx->completed = 0; ctx->completed = 0;
simple = g_simple_async_result_new (NULL, callback, user_data, task = g_task_new (NULL, cancellable, callback, user_data);
g_io_stream_splice_finish); g_task_set_task_data (task, ctx, (GDestroyNotify) splice_context_free);
g_simple_async_result_set_op_res_gpointer (simple, ctx,
(GDestroyNotify) splice_context_free);
if (cancellable != NULL) if (cancellable != NULL)
{ {
ctx->cancellable = g_object_ref (cancellable); ctx->cancellable = g_object_ref (cancellable);
ctx->cancelled_id = g_cancellable_connect (cancellable, ctx->cancelled_id = g_cancellable_connect (cancellable,
G_CALLBACK (splice_cancelled_cb), g_object_ref (simple), G_CALLBACK (splice_cancelled_cb), g_object_ref (task),
g_object_unref); g_object_unref);
} }
@ -804,15 +799,15 @@ g_io_stream_splice_async (GIOStream *stream1,
ostream = g_io_stream_get_output_stream (stream2); ostream = g_io_stream_get_output_stream (stream2);
g_output_stream_splice_async (ostream, istream, G_OUTPUT_STREAM_SPLICE_NONE, g_output_stream_splice_async (ostream, istream, G_OUTPUT_STREAM_SPLICE_NONE,
io_priority, ctx->op1_cancellable, splice_cb, io_priority, ctx->op1_cancellable, splice_cb,
g_object_ref (simple)); g_object_ref (task));
istream = g_io_stream_get_input_stream (stream2); istream = g_io_stream_get_input_stream (stream2);
ostream = g_io_stream_get_output_stream (stream1); ostream = g_io_stream_get_output_stream (stream1);
g_output_stream_splice_async (ostream, istream, G_OUTPUT_STREAM_SPLICE_NONE, g_output_stream_splice_async (ostream, istream, G_OUTPUT_STREAM_SPLICE_NONE,
io_priority, ctx->op2_cancellable, splice_cb, io_priority, ctx->op2_cancellable, splice_cb,
g_object_ref (simple)); g_object_ref (task));
g_object_unref (simple); g_object_unref (task);
} }
/** /**
@ -831,17 +826,7 @@ gboolean
g_io_stream_splice_finish (GAsyncResult *result, g_io_stream_splice_finish (GAsyncResult *result,
GError **error) GError **error)
{ {
GSimpleAsyncResult *simple; g_return_val_if_fail (g_task_is_valid (result, NULL), FALSE);
g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE); return g_task_propagate_boolean (G_TASK (result), error);
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return FALSE;
g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL,
g_io_stream_splice_finish), FALSE);
return TRUE;
} }

View File

@ -26,7 +26,7 @@
#include "ginputstream.h" #include "ginputstream.h"
#include "gseekable.h" #include "gseekable.h"
#include "string.h" #include "string.h"
#include "gsimpleasyncresult.h" #include "gtask.h"
#include "gioerror.h" #include "gioerror.h"
#include "glibintl.h" #include "glibintl.h"
@ -377,17 +377,13 @@ g_memory_input_stream_skip_async (GInputStream *stream,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
GSimpleAsyncResult *simple; GTask *task;
gssize nskipped; gssize nskipped;
nskipped = g_input_stream_skip (stream, count, cancellable, NULL); nskipped = g_input_stream_skip (stream, count, cancellable, NULL);
simple = g_simple_async_result_new (G_OBJECT (stream), task = g_task_new (stream, cancellable, callback, user_data);
callback, g_task_return_int (task, nskipped);
user_data, g_object_unref (task);
g_memory_input_stream_skip_async);
g_simple_async_result_set_op_res_gssize (simple, nskipped);
g_simple_async_result_complete_in_idle (simple);
g_object_unref (simple);
} }
static gssize static gssize
@ -395,14 +391,9 @@ g_memory_input_stream_skip_finish (GInputStream *stream,
GAsyncResult *result, GAsyncResult *result,
GError **error) GError **error)
{ {
GSimpleAsyncResult *simple; g_return_val_if_fail (g_task_is_valid (result, stream), -1);
gssize nskipped;
simple = G_SIMPLE_ASYNC_RESULT (result); return g_task_propagate_int (G_TASK (result), error);
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_memory_input_stream_skip_async);
nskipped = g_simple_async_result_get_op_res_gssize (simple);
return nskipped;
} }
static void static void
@ -412,14 +403,11 @@ g_memory_input_stream_close_async (GInputStream *stream,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
GSimpleAsyncResult *simple; GTask *task;
simple = g_simple_async_result_new (G_OBJECT (stream), task = g_task_new (stream, cancellable, callback, user_data);
callback, g_task_return_boolean (task, TRUE);
user_data, g_object_unref (task);
g_memory_input_stream_close_async);
g_simple_async_result_complete_in_idle (simple);
g_object_unref (simple);
} }
static gboolean static gboolean

View File

@ -27,7 +27,7 @@
#include "goutputstream.h" #include "goutputstream.h"
#include "gpollableoutputstream.h" #include "gpollableoutputstream.h"
#include "gseekable.h" #include "gseekable.h"
#include "gsimpleasyncresult.h" #include "gtask.h"
#include "gioerror.h" #include "gioerror.h"
#include "string.h" #include "string.h"
#include "glibintl.h" #include "glibintl.h"
@ -665,19 +665,15 @@ g_memory_output_stream_close_async (GOutputStream *stream,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer data) gpointer data)
{ {
GSimpleAsyncResult *simple; GTask *task;
simple = g_simple_async_result_new (G_OBJECT (stream),
callback,
data,
g_memory_output_stream_close_async);
task = g_task_new (stream, cancellable, callback, data);
/* will always return TRUE */ /* will always return TRUE */
g_memory_output_stream_close (stream, cancellable, NULL); g_memory_output_stream_close (stream, cancellable, NULL);
g_simple_async_result_complete_in_idle (simple); g_task_return_boolean (task, TRUE);
g_object_unref (simple); g_object_unref (task);
} }
static gboolean static gboolean
@ -685,14 +681,9 @@ g_memory_output_stream_close_finish (GOutputStream *stream,
GAsyncResult *result, GAsyncResult *result,
GError **error) GError **error)
{ {
GSimpleAsyncResult *simple; g_return_val_if_fail (g_task_is_valid (result, stream), -1);
simple = G_SIMPLE_ASYNC_RESULT (result); return g_task_propagate_boolean (G_TASK (result), error);
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) ==
g_memory_output_stream_close_async);
return TRUE;
} }
static goffset static goffset

File diff suppressed because it is too large Load Diff

View File

@ -425,8 +425,6 @@ g_unix_input_stream_close (GInputStream *stream,
if (!unix_stream->priv->close_fd) if (!unix_stream->priv->close_fd)
return TRUE; return TRUE;
while (1)
{
/* This might block during the close. Doesn't seem to be a way to avoid it though. */ /* This might block during the close. Doesn't seem to be a way to avoid it though. */
res = close (unix_stream->priv->fd); res = close (unix_stream->priv->fd);
if (res == -1) if (res == -1)
@ -438,8 +436,6 @@ g_unix_input_stream_close (GInputStream *stream,
_("Error closing file descriptor: %s"), _("Error closing file descriptor: %s"),
g_strerror (errsv)); g_strerror (errsv));
} }
break;
}
return res != -1; return res != -1;
} }
@ -466,71 +462,6 @@ g_unix_input_stream_skip_finish (GInputStream *stream,
/* TODO: Not implemented */ /* TODO: Not implemented */
} }
typedef struct {
GInputStream *stream;
GAsyncReadyCallback callback;
gpointer user_data;
} CloseAsyncData;
static void
close_async_data_free (gpointer _data)
{
CloseAsyncData *data = _data;
g_free (data);
}
static gboolean
close_async_cb (CloseAsyncData *data)
{
GUnixInputStream *unix_stream;
GSimpleAsyncResult *simple;
GError *error = NULL;
gboolean result;
int res;
unix_stream = G_UNIX_INPUT_STREAM (data->stream);
if (!unix_stream->priv->close_fd)
{
result = TRUE;
goto out;
}
while (1)
{
res = close (unix_stream->priv->fd);
if (res == -1)
{
int errsv = errno;
g_set_error (&error, G_IO_ERROR,
g_io_error_from_errno (errsv),
_("Error closing file descriptor: %s"),
g_strerror (errsv));
}
break;
}
result = res != -1;
out:
simple = g_simple_async_result_new (G_OBJECT (data->stream),
data->callback,
data->user_data,
g_unix_input_stream_close_async);
if (!result)
g_simple_async_result_take_error (simple, error);
/* Complete immediately, not in idle, since we're already in a mainloop callout */
g_simple_async_result_complete (simple);
g_object_unref (simple);
return FALSE;
}
static void static void
g_unix_input_stream_close_async (GInputStream *stream, g_unix_input_stream_close_async (GInputStream *stream,
int io_priority, int io_priority,
@ -538,19 +469,17 @@ g_unix_input_stream_close_async (GInputStream *stream,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
GSource *idle; GTask *task;
CloseAsyncData *data; GError *error = NULL;
data = g_new0 (CloseAsyncData, 1); task = g_task_new (stream, cancellable, callback, user_data);
g_task_set_priority (task, io_priority);
data->stream = stream; if (g_unix_input_stream_close (stream, cancellable, &error))
data->callback = callback; g_task_return_boolean (task, TRUE);
data->user_data = user_data; else
g_task_return_error (task, error);
idle = g_idle_source_new (); g_object_unref (task);
g_source_set_callback (idle, (GSourceFunc)close_async_cb, data, close_async_data_free);
g_source_attach (idle, g_main_context_get_thread_default ());
g_source_unref (idle);
} }
static gboolean static gboolean
@ -558,8 +487,9 @@ g_unix_input_stream_close_finish (GInputStream *stream,
GAsyncResult *result, GAsyncResult *result,
GError **error) GError **error)
{ {
/* Failures handled in generic close_finish code */ g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
return TRUE;
return g_task_propagate_boolean (G_TASK (result), error);
} }
static gboolean static gboolean

View File

@ -411,8 +411,6 @@ g_unix_output_stream_close (GOutputStream *stream,
if (!unix_stream->priv->close_fd) if (!unix_stream->priv->close_fd)
return TRUE; return TRUE;
while (1)
{
/* This might block during the close. Doesn't seem to be a way to avoid it though. */ /* This might block during the close. Doesn't seem to be a way to avoid it though. */
res = close (unix_stream->priv->fd); res = close (unix_stream->priv->fd);
if (res == -1) if (res == -1)
@ -424,68 +422,10 @@ g_unix_output_stream_close (GOutputStream *stream,
_("Error closing file descriptor: %s"), _("Error closing file descriptor: %s"),
g_strerror (errsv)); g_strerror (errsv));
} }
break;
}
return res != -1; return res != -1;
} }
typedef struct {
GOutputStream *stream;
GAsyncReadyCallback callback;
gpointer user_data;
} CloseAsyncData;
static gboolean
close_async_cb (CloseAsyncData *data)
{
GUnixOutputStream *unix_stream;
GSimpleAsyncResult *simple;
GError *error = NULL;
gboolean result;
int res;
unix_stream = G_UNIX_OUTPUT_STREAM (data->stream);
if (!unix_stream->priv->close_fd)
{
result = TRUE;
goto out;
}
while (1)
{
res = close (unix_stream->priv->fd);
if (res == -1)
{
int errsv = errno;
g_set_error (&error, G_IO_ERROR,
g_io_error_from_errno (errsv),
_("Error closing file descriptor: %s"),
g_strerror (errsv));
}
break;
}
result = res != -1;
out:
simple = g_simple_async_result_new (G_OBJECT (data->stream),
data->callback,
data->user_data,
g_unix_output_stream_close_async);
if (!result)
g_simple_async_result_take_error (simple, error);
/* Complete immediately, not in idle, since we're already in a mainloop callout */
g_simple_async_result_complete (simple);
g_object_unref (simple);
return FALSE;
}
static void static void
g_unix_output_stream_close_async (GOutputStream *stream, g_unix_output_stream_close_async (GOutputStream *stream,
int io_priority, int io_priority,
@ -493,19 +433,17 @@ g_unix_output_stream_close_async (GOutputStream *stream,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,
gpointer user_data) gpointer user_data)
{ {
GSource *idle; GTask *task;
CloseAsyncData *data; GError *error = NULL;
data = g_new0 (CloseAsyncData, 1); task = g_task_new (stream, cancellable, callback, user_data);
g_task_set_priority (task, io_priority);
data->stream = stream; if (g_unix_output_stream_close (stream, cancellable, &error))
data->callback = callback; g_task_return_boolean (task, TRUE);
data->user_data = user_data; else
g_task_return_error (task, error);
idle = g_idle_source_new (); g_object_unref (task);
g_source_set_callback (idle, (GSourceFunc)close_async_cb, data, g_free);
g_source_attach (idle, g_main_context_get_thread_default ());
g_source_unref (idle);
} }
static gboolean static gboolean
@ -513,8 +451,9 @@ g_unix_output_stream_close_finish (GOutputStream *stream,
GAsyncResult *result, GAsyncResult *result,
GError **error) GError **error)
{ {
/* Failures handled in generic close_finish code */ g_return_val_if_fail (g_task_is_valid (result, stream), FALSE);
return TRUE;
return g_task_propagate_boolean (G_TASK (result), error);
} }
static gboolean static gboolean