summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Toso <victortoso@redhat.com>2015-05-15 17:46:27 +0200
committerVictor Toso <victortoso@redhat.com>2015-06-05 09:22:32 +0200
commit5cf5f631cc5f74ce8d1d462d06a80cb71b3121ed (patch)
tree7cdbc824ef2231fa3a51b01ec614b505a72dc679
parent01540664bd0608a02a0be787eb548709f3d68fe1 (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.c63
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;
}