diff options
author | Victor Toso <victortoso@redhat.com> | 2015-05-15 17:46:27 +0200 |
---|---|---|
committer | Victor Toso <victortoso@redhat.com> | 2015-06-05 09:22:32 +0200 |
commit | 5cf5f631cc5f74ce8d1d462d06a80cb71b3121ed (patch) | |
tree | 7cdbc824ef2231fa3a51b01ec614b505a72dc679 | |
parent | 01540664bd0608a02a0be787eb548709f3d68fe1 (diff) |
giopipe: don't fail on create_source
PipeInputStream and PipeOutputStream should not fail when creating
GPollableStream source as this currently does not work with default
write_all and read_all functions;
In order to avoid creating zombie GSource in create_source of both
PipeInputStream and PipeOutputStream, we track all created GSources and
set them to be dispatched when data is available to read/write. It is
worth to mention that concurrent write/read is not possible with current
giopipe and only the last created GSource will read the data as it is
dispatched first.
-rw-r--r-- | gtk/giopipe.c | 63 |
1 files changed, 33 insertions, 30 deletions
diff --git a/gtk/giopipe.c b/gtk/giopipe.c index 50edb5b..d91c4d9 100644 --- a/gtk/giopipe.c +++ b/gtk/giopipe.c @@ -44,7 +44,7 @@ struct _PipeInputStream * closing. */ gboolean peer_closed; - GSource *source; + GList *sources; }; struct _PipeInputStreamClass @@ -69,7 +69,7 @@ struct _PipeOutputStream const gchar *buffer; gsize count; gboolean peer_closed; - GSource *source; + GList *sources; }; struct _PipeOutputStreamClass @@ -120,12 +120,32 @@ pipe_input_stream_read (GInputStream *stream, return count; } +static GList * +set_all_sources_ready (GList *sources) +{ + GList *it = sources; + while (it != NULL) { + GSource *s = it->data; + GList *next = it->next; + + if (s == NULL || g_source_is_destroyed(s)) { + /* remove */ + sources = g_list_delete_link(sources, it); + g_source_unref(s); + } else { + /* dispatch */ + g_source_set_ready_time(s, 0); + } + it = next; + } + return sources; +} + static void pipe_input_stream_check_source (PipeInputStream *self) { - if (self->source && !g_source_is_destroyed(self->source) && - g_pollable_input_stream_is_readable(G_POLLABLE_INPUT_STREAM(self))) - g_source_set_ready_time(self->source, 0); + if (g_pollable_input_stream_is_readable(G_POLLABLE_INPUT_STREAM(self))) + self->sources = set_all_sources_ready(self->sources); } static gboolean @@ -193,10 +213,8 @@ pipe_input_stream_dispose(GObject *object) self->peer = NULL; } - if (self->source) { - g_source_unref(self->source); - self->source = NULL; - } + g_list_free_full (self->sources, (GDestroyNotify) g_source_unref); + self->sources = NULL; G_OBJECT_CLASS(pipe_input_stream_parent_class)->dispose (object); } @@ -234,14 +252,8 @@ pipe_input_stream_create_source (GPollableInputStream *stream, PipeInputStream *self = PIPE_INPUT_STREAM(stream); GSource *pollable_source; - g_return_val_if_fail (self->source == NULL || - g_source_is_destroyed (self->source), NULL); - - if (self->source && g_source_is_destroyed (self->source)) - g_source_unref (self->source); - pollable_source = g_pollable_source_new_full (self, NULL, cancellable); - self->source = g_source_ref (pollable_source); + self->sources = g_list_prepend (self->sources, g_source_ref (pollable_source)); return pollable_source; } @@ -319,10 +331,8 @@ pipe_output_stream_dispose(GObject *object) self->peer = NULL; } - if (self->source) { - g_source_unref(self->source); - self->source = NULL; - } + g_list_free_full (self->sources, (GDestroyNotify) g_source_unref); + self->sources = NULL; G_OBJECT_CLASS(pipe_output_stream_parent_class)->dispose (object); } @@ -330,9 +340,8 @@ pipe_output_stream_dispose(GObject *object) static void pipe_output_stream_check_source (PipeOutputStream *self) { - if (self->source && !g_source_is_destroyed(self->source) && - g_pollable_output_stream_is_writable(G_POLLABLE_OUTPUT_STREAM(self))) - g_source_set_ready_time(self->source, 0); + if (g_pollable_output_stream_is_writable(G_POLLABLE_OUTPUT_STREAM(self))) + self->sources = set_all_sources_ready(self->sources); } static gboolean @@ -416,14 +425,8 @@ pipe_output_stream_create_source (GPollableOutputStream *stream, PipeOutputStream *self = PIPE_OUTPUT_STREAM(stream); GSource *pollable_source; - g_return_val_if_fail (self->source == NULL || - g_source_is_destroyed (self->source), NULL); - - if (self->source && g_source_is_destroyed (self->source)) - g_source_unref (self->source); - pollable_source = g_pollable_source_new_full (self, NULL, cancellable); - self->source = g_source_ref (pollable_source); + self->sources = g_list_prepend (self->sources, g_source_ref (pollable_source)); return pollable_source; } |