Add pollable input/output streams

When interfacing with APIs that expect unix-style async I/O, it is
useful to be able to tell in advance whether a read/write is going to
block. This adds new interfaces GPollableInputStream and
GPollableOutputStream that can be implemented by a GInputStream or
GOutputStream to add _is_readable/_is_writable, _create_source, and
_read_nonblocking/_write_nonblocking methods.

Also, implement for GUnixInput/OutputStream and
GSocketInput/OutputStream

https://bugzilla.gnome.org/show_bug.cgi?id=634241
This commit is contained in:
Dan Winship
2010-09-18 13:05:25 -04:00
parent 6181c7de36
commit c20c2c0abd
19 changed files with 1251 additions and 12 deletions

View File

@@ -60,8 +60,12 @@ enum {
PROP_CLOSE_FD
};
G_DEFINE_TYPE (GUnixOutputStream, g_unix_output_stream, G_TYPE_OUTPUT_STREAM);
static void g_unix_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GUnixOutputStream, g_unix_output_stream, G_TYPE_OUTPUT_STREAM,
G_IMPLEMENT_INTERFACE (G_TYPE_POLLABLE_OUTPUT_STREAM,
g_unix_output_stream_pollable_iface_init)
);
struct _GUnixOutputStreamPrivate {
int fd;
@@ -103,6 +107,9 @@ static gboolean g_unix_output_stream_close_finish (GOutputStream *stream,
GAsyncResult *result,
GError **error);
static gboolean g_unix_output_stream_pollable_is_writable (GPollableOutputStream *stream);
static GSource *g_unix_output_stream_pollable_create_source (GPollableOutputStream *stream,
GCancellable *cancellable);
static void
g_unix_output_stream_finalize (GObject *object)
@@ -160,6 +167,13 @@ g_unix_output_stream_class_init (GUnixOutputStreamClass *klass)
G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
}
static void
g_unix_output_stream_pollable_iface_init (GPollableOutputStreamInterface *iface)
{
iface->is_writable = g_unix_output_stream_pollable_is_writable;
iface->create_source = g_unix_output_stream_pollable_create_source;
}
static void
g_unix_output_stream_set_property (GObject *object,
guint prop_id,
@@ -593,3 +607,37 @@ g_unix_output_stream_close_finish (GOutputStream *stream,
/* Failures handled in generic close_finish code */
return TRUE;
}
static gboolean
g_unix_output_stream_pollable_is_writable (GPollableOutputStream *stream)
{
GUnixOutputStream *unix_stream = G_UNIX_OUTPUT_STREAM (stream);
GPollFD poll_fd;
gint result;
poll_fd.fd = unix_stream->priv->fd;
poll_fd.events = G_IO_OUT;
do
result = g_poll (&poll_fd, 1, 0);
while (result == -1 && errno == EINTR);
return poll_fd.revents != 0;
}
static GSource *
g_unix_output_stream_pollable_create_source (GPollableOutputStream *stream,
GCancellable *cancellable)
{
GUnixOutputStream *unix_stream = G_UNIX_OUTPUT_STREAM (stream);
GSource *inner_source, *pollable_source;
pollable_source = g_pollable_source_new (G_OBJECT (stream));
inner_source = _g_fd_source_new (unix_stream->priv->fd, G_IO_OUT, cancellable);
g_source_set_dummy_callback (inner_source);
g_source_add_child_source (pollable_source, inner_source);
g_source_unref (inner_source);
return pollable_source;
}