gio: use GPollable* to implement fallback read_async/write_async

If a GInputStream does not provide a read_async() implementation, but
does implement GPollableInputStream, then instead of doing
read-synchronously-in-a-thread, just use
g_pollable_input_stream_read_nonblocking() and
g_pollable_input_stream_create_source() to implement an async read in
the same thread. Similarly for GOutputStream.

Remove a bunch of existing read_async()/write_async() implementations
that are basically equivalent to the new fallback method.

https://bugzilla.gnome.org/show_bug.cgi?id=673997
This commit is contained in:
Dan Winship
2012-02-04 16:46:29 -05:00
parent 82ec4dcaed
commit 00ee06e6a3
10 changed files with 153 additions and 892 deletions

View File

@@ -28,7 +28,7 @@
#include "ginputstream.h"
#include "gioerror.h"
#include "glibintl.h"
#include "gpollableoutputstream.h"
/**
* SECTION:goutputstream
@@ -1266,6 +1266,10 @@ typedef struct {
const void *buffer;
gsize count_requested;
gssize count_written;
GCancellable *cancellable;
gint io_priority;
gboolean need_idle;
} WriteData;
static void
@@ -1285,6 +1289,60 @@ write_async_thread (GSimpleAsyncResult *res,
g_simple_async_result_take_error (res, error);
}
static void write_async_pollable (GPollableOutputStream *stream,
GSimpleAsyncResult *result);
static gboolean
write_async_pollable_ready (GPollableOutputStream *stream,
gpointer user_data)
{
GSimpleAsyncResult *result = user_data;
write_async_pollable (stream, result);
return FALSE;
}
static void
write_async_pollable (GPollableOutputStream *stream,
GSimpleAsyncResult *result)
{
GError *error = NULL;
WriteData *op = g_simple_async_result_get_op_res_gpointer (result);
if (g_cancellable_set_error_if_cancelled (op->cancellable, &error))
op->count_written = -1;
else
{
op->count_written = G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE (stream)->
write_nonblocking (stream, op->buffer, op->count_requested, &error);
}
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
{
GSource *source;
g_error_free (error);
op->need_idle = FALSE;
source = g_pollable_output_stream_create_source (stream, op->cancellable);
g_source_set_callback (source,
(GSourceFunc) write_async_pollable_ready,
g_object_ref (result), g_object_unref);
g_source_set_priority (source, op->io_priority);
g_source_attach (source, g_main_context_get_thread_default ());
g_source_unref (source);
return;
}
if (op->count_written == -1)
g_simple_async_result_take_error (result, error);
if (op->need_idle)
g_simple_async_result_complete_in_idle (result);
else
g_simple_async_result_complete (result);
}
static void
g_output_stream_real_write_async (GOutputStream *stream,
const void *buffer,
@@ -1303,7 +1361,11 @@ g_output_stream_real_write_async (GOutputStream *stream,
op->buffer = buffer;
op->count_requested = count;
g_simple_async_result_run_in_thread (res, write_async_thread, io_priority, cancellable);
if (G_IS_POLLABLE_OUTPUT_STREAM (stream) &&
g_pollable_output_stream_can_poll (G_POLLABLE_OUTPUT_STREAM (stream)))
write_async_pollable (G_POLLABLE_OUTPUT_STREAM (stream), res);
else
g_simple_async_result_run_in_thread (res, write_async_thread, io_priority, cancellable);
g_object_unref (res);
}