[Spice-commits] 7 commits - gtk/channel-base.c gtk/channel-display.c gtk/channel-main.c gtk/decode-glz.c gtk/gio-coroutine.c gtk/gio-coroutine.h gtk/spice-channel.c gtk/spice-channel-priv.h gtk/spice-session.c gtk/spice-session-priv.h
Marc-André Lureau
elmarco at kemper.freedesktop.org
Fri Jan 13 08:21:05 PST 2012
gtk/channel-base.c | 7 +-
gtk/channel-display.c | 66 ++++++++++++++++--------
gtk/channel-main.c | 10 +--
gtk/decode-glz.c | 4 +
gtk/gio-coroutine.c | 127 +++++++++++++++++++++++++++++------------------
gtk/gio-coroutine.h | 31 +++++------
gtk/spice-channel-priv.h | 5 -
gtk/spice-channel.c | 35 +++++++-----
gtk/spice-session-priv.h | 3 -
gtk/spice-session.c | 14 +++--
10 files changed, 183 insertions(+), 119 deletions(-)
New commits:
commit ecfe99f7c406a70c16c9fa5ded66b73425c2bd20
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Mon Jan 9 18:11:33 2012 +0100
wait for cached images that haven't been added to the cache yet
https://bugs.freedesktop.org/show_bug.cgi?id=44570
diff --git a/gtk/channel-display.c b/gtk/channel-display.c
index d5061da..ec42829 100644
--- a/gtk/channel-display.c
+++ b/gtk/channel-display.c
@@ -404,18 +404,44 @@ static void image_put(SpiceImageCache *cache, uint64_t id, pixman_image_t *image
item->ptr = pixman_image_ref(image);
}
-static pixman_image_t *image_get(SpiceImageCache *cache, uint64_t id)
+typedef struct _WaitImageData
+{
+ gboolean lossy;
+ SpiceImageCache *cache;
+ uint64_t id;
+ pixman_image_t *image;
+} WaitImageData;
+
+static gboolean wait_image(gpointer data)
{
- SpiceDisplayChannelPrivate *c =
- SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, image_cache);
display_cache_item *item;
+ WaitImageData *wait = data;
+ SpiceDisplayChannelPrivate *c =
+ SPICE_CONTAINEROF(wait->cache, SpiceDisplayChannelPrivate, image_cache);
- item = cache_find(c->images, id);
- if (item) {
- cache_used(c->images, item);
- return pixman_image_ref(item->ptr);
- }
- return NULL;
+ item = cache_find(c->images, wait->id);
+ if (item == NULL ||
+ (item->lossy && !wait->lossy))
+ return FALSE;
+
+ cache_used(c->images, item);
+ wait->image = pixman_image_ref(item->ptr);
+
+ return TRUE;
+}
+
+static pixman_image_t *image_get(SpiceImageCache *cache, uint64_t id)
+{
+ WaitImageData wait = {
+ .lossy = TRUE,
+ .cache = cache,
+ .id = id,
+ .image = NULL
+ };
+ if (!g_coroutine_condition_wait(g_coroutine_self(), wait_image, &wait))
+ SPICE_DEBUG("wait image got cancelled");
+
+ return wait.image;
}
static void image_remove(SpiceImageCache *cache, uint64_t id)
@@ -511,20 +537,16 @@ static void image_replace_lossy(SpiceImageCache *cache, uint64_t id,
static pixman_image_t* image_get_lossless(SpiceImageCache *cache, uint64_t id)
{
- SpiceDisplayChannelPrivate *c =
- SPICE_CONTAINEROF(cache, SpiceDisplayChannelPrivate, image_cache);
- display_cache_item *item;
-
- item = cache_find(c->images, id);
- if (!item)
- return NULL;
-
- /* TODO: shared_cache.hpp does wait until it is lossless..., is
- that necessary? */
- g_warn_if_fail(item->lossy == FALSE);
+ WaitImageData wait = {
+ .lossy = FALSE,
+ .cache = cache,
+ .id = id,
+ .image = NULL
+ };
+ if (!g_coroutine_condition_wait(g_coroutine_self(), wait_image, &wait))
+ SPICE_DEBUG("wait lossless got cancelled");
- cache_used(c->images, item);
- return pixman_image_ref(item->ptr);
+ return wait.image;
}
#endif
commit 2d2a5b55b718ad8ee4822999e979d1ca4811deb8
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Mon Jan 9 17:42:14 2012 +0100
Log if condition wait got cancelled
https://bugs.freedesktop.org/show_bug.cgi?id=44570
diff --git a/gtk/channel-base.c b/gtk/channel-base.c
index fd36696..b01be23 100644
--- a/gtk/channel-base.c
+++ b/gtk/channel-base.c
@@ -130,8 +130,10 @@ void spice_channel_handle_wait_for_channels(SpiceChannel *channel, SpiceMsgIn *i
};
SPICE_DEBUG("waiting for serial %lu (%d/%d)", data.wait->message_serial, i + 1, wfc->wait_count);
- g_coroutine_condition_wait(&c->coroutine, wait_for_channel, &data);
- SPICE_DEBUG("waiting for serial %lu, done", data.wait->message_serial);
+ if (g_coroutine_condition_wait(&c->coroutine, wait_for_channel, &data))
+ SPICE_DEBUG("waiting for serial %lu, done", data.wait->message_serial);
+ else
+ SPICE_DEBUG("waiting for serial %lu, cancelled", data.wait->message_serial);
}
}
diff --git a/gtk/decode-glz.c b/gtk/decode-glz.c
index 377f7af..3b7c34b 100644
--- a/gtk/decode-glz.c
+++ b/gtk/decode-glz.c
@@ -153,7 +153,9 @@ static void *glz_decoder_window_bits(SpiceGlzDecoderWindow *w, uint64_t id,
.id = id - dist,
};
- g_coroutine_condition_wait(g_coroutine_self(), wait_for_image, &data);
+ if (!g_coroutine_condition_wait(g_coroutine_self(), wait_for_image, &data))
+ SPICE_DEBUG("wait for image cancelled");
+
slot = (id - dist) % w->nimages;
}
diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 9316f90..ed0ca8b 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -1997,9 +1997,9 @@ static gboolean spice_channel_iterate(SpiceChannel *channel)
GIOCondition ret;
do {
- /* freeze coroutine */
- if (c->state == SPICE_CHANNEL_STATE_MIGRATING)
- g_coroutine_condition_wait(&c->coroutine, wait_migration, channel);
+ if (c->state == SPICE_CHANNEL_STATE_MIGRATING &&
+ !g_coroutine_condition_wait(&c->coroutine, wait_migration, channel))
+ SPICE_DEBUG("migration wait cancelled");
if (c->has_error) {
SPICE_DEBUG("channel has error, breaking loop");
commit 173841cb216c244580f72d61892f67f91a4c7b8a
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Mon Jan 9 16:34:16 2012 +0100
Make g_coroutine_condition_wait() cancellable
https://bugs.freedesktop.org/show_bug.cgi?id=44570
diff --git a/gtk/channel-base.c b/gtk/channel-base.c
index e41b1f5..fd36696 100644
--- a/gtk/channel-base.c
+++ b/gtk/channel-base.c
@@ -116,6 +116,7 @@ static gboolean wait_for_channel(gpointer data)
G_GNUC_INTERNAL
void spice_channel_handle_wait_for_channels(SpiceChannel *channel, SpiceMsgIn *in)
{
+ SpiceChannelPrivate *c = channel->priv;
SpiceMsgWaitForChannels *wfc = spice_msg_in_parsed(in);
int i;
@@ -129,7 +130,7 @@ void spice_channel_handle_wait_for_channels(SpiceChannel *channel, SpiceMsgIn *i
};
SPICE_DEBUG("waiting for serial %lu (%d/%d)", data.wait->message_serial, i + 1, wfc->wait_count);
- g_condition_wait(wait_for_channel, &data);
+ g_coroutine_condition_wait(&c->coroutine, wait_for_channel, &data);
SPICE_DEBUG("waiting for serial %lu, done", data.wait->message_serial);
}
}
diff --git a/gtk/channel-main.c b/gtk/channel-main.c
index 42e4494..ebf660f 100644
--- a/gtk/channel-main.c
+++ b/gtk/channel-main.c
@@ -1709,7 +1709,7 @@ static gboolean timer_set_display(gpointer data)
c->timer_id = 0;
if (c->agent_connected)
spice_main_send_monitor_config(SPICE_MAIN_CHANNEL(channel));
- spice_channel_wakeup(channel);
+ spice_channel_wakeup(channel, FALSE);
return false;
}
@@ -1783,7 +1783,7 @@ void spice_main_clipboard_selection_grab(SpiceMainChannel *channel, guint select
g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel));
agent_clipboard_grab(channel, selection, types, ntypes);
- spice_channel_wakeup(SPICE_CHANNEL(channel));
+ spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
}
/**
@@ -1822,7 +1822,7 @@ void spice_main_clipboard_selection_release(SpiceMainChannel *channel, guint sel
return;
agent_clipboard_release(channel, selection);
- spice_channel_wakeup(SPICE_CHANNEL(channel));
+ spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
}
/**
@@ -1863,7 +1863,7 @@ void spice_main_clipboard_selection_notify(SpiceMainChannel *channel, guint sele
g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel));
agent_clipboard_notify(channel, selection, type, data, size);
- spice_channel_wakeup(SPICE_CHANNEL(channel));
+ spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
}
/**
@@ -1899,7 +1899,7 @@ void spice_main_clipboard_selection_request(SpiceMainChannel *channel, guint sel
g_return_if_fail(SPICE_IS_MAIN_CHANNEL(channel));
agent_clipboard_request(channel, selection, type);
- spice_channel_wakeup(SPICE_CHANNEL(channel));
+ spice_channel_wakeup(SPICE_CHANNEL(channel), FALSE);
}
/**
diff --git a/gtk/decode-glz.c b/gtk/decode-glz.c
index 317fa9e..377f7af 100644
--- a/gtk/decode-glz.c
+++ b/gtk/decode-glz.c
@@ -153,7 +153,7 @@ static void *glz_decoder_window_bits(SpiceGlzDecoderWindow *w, uint64_t id,
.id = id - dist,
};
- g_condition_wait(wait_for_image, &data);
+ g_coroutine_condition_wait(g_coroutine_self(), wait_for_image, &data);
slot = (id - dist) % w->nimages;
}
diff --git a/gtk/gio-coroutine.c b/gtk/gio-coroutine.c
index 806dad9..355c75c 100644
--- a/gtk/gio-coroutine.c
+++ b/gtk/gio-coroutine.c
@@ -23,8 +23,8 @@
typedef struct _GConditionWaitSource
{
+ GCoroutine *self;
GSource src;
- struct coroutine *co;
GConditionWaitFunc func;
gpointer data;
} GConditionWaitSource;
@@ -70,6 +70,17 @@ GIOCondition g_coroutine_socket_wait(GCoroutine *self,
return val;
}
+void g_coroutine_condition_cancel(GCoroutine *coroutine)
+{
+ g_return_if_fail(coroutine != NULL);
+
+ if (coroutine->condition_id == 0)
+ return;
+
+ g_source_remove(coroutine->condition_id);
+ coroutine->condition_id = 0;
+}
+
void g_coroutine_wakeup(GCoroutine *coroutine)
{
g_return_if_fail(coroutine != NULL);
@@ -79,7 +90,6 @@ void g_coroutine_wakeup(GCoroutine *coroutine)
coroutine_yieldto(&coroutine->coroutine, NULL);
}
-
/*
* Call immediately before the main loop does an iteration. Returns
* true if the condition we're checking is ready for dispatch
@@ -120,15 +130,32 @@ static gboolean g_condition_wait_helper(gpointer data)
return FALSE;
}
-gboolean g_condition_wait(GConditionWaitFunc func, gpointer data)
+/*
+ * g_coroutine_condition_wait:
+ * @coroutine: the coroutine to wait on
+ * @func: the condition callback
+ * @data: the user data passed to @func callback
+ *
+ * This function will wait on caller coroutine until @func returns %TRUE.
+ *
+ * @func is called when entering the main loop from the main context (coroutine).
+ *
+ * The condition can be cancelled by calling g_coroutine_wakeup()
+ *
+ * Returns: %TRUE if condition reached, %FALSE if not and cancelled
+ */
+gboolean g_coroutine_condition_wait(GCoroutine *self, GConditionWaitFunc func, gpointer data)
{
GSource *src;
GConditionWaitSource *vsrc;
+ g_return_val_if_fail(self != NULL, FALSE);
+ g_return_val_if_fail(self->condition_id == 0, FALSE);
+ g_return_val_if_fail(func != NULL, FALSE);
+
/* Short-circuit check in case we've got it ahead of time */
- if (func(data)) {
+ if (func(data))
return TRUE;
- }
/*
* Don't have it, so yield to the main loop, checking the condition
@@ -139,13 +166,18 @@ gboolean g_condition_wait(GConditionWaitFunc func, gpointer data)
vsrc->func = func;
vsrc->data = data;
- vsrc->co = coroutine_self();
+ vsrc->self = self;
- g_source_attach(src, NULL);
- g_source_set_callback(src, g_condition_wait_helper, coroutine_self(), NULL);
+ self->condition_id = g_source_attach(src, NULL);
+ g_source_set_callback(src, g_condition_wait_helper, self, NULL);
coroutine_yield(NULL);
g_source_unref(src);
+ /* it got woked up / cancelled? */
+ if (self->condition_id == 0)
+ return func(data);
+
+ self->condition_id = 0;
return TRUE;
}
diff --git a/gtk/gio-coroutine.h b/gtk/gio-coroutine.h
index cb96a52..1c4094e 100644
--- a/gtk/gio-coroutine.h
+++ b/gtk/gio-coroutine.h
@@ -32,6 +32,7 @@ struct _GCoroutine
{
struct coroutine coroutine;
guint wait_id;
+ guint condition_id;
};
/*
@@ -47,11 +48,14 @@ typedef gboolean (*GConditionWaitFunc)(gpointer);
typedef void (*GSignalEmitMainFunc)(GObject *object, int signum, gpointer params);
-GCoroutine* g_coroutine_self (void);
-void g_coroutine_wakeup (GCoroutine *coroutine);
-GIOCondition g_coroutine_socket_wait(GCoroutine *coroutine, GSocket *sock, GIOCondition cond);
+GCoroutine* g_coroutine_self (void);
+void g_coroutine_wakeup (GCoroutine *coroutine);
+GIOCondition g_coroutine_socket_wait (GCoroutine *coroutine,
+ GSocket *sock, GIOCondition cond);
+gboolean g_coroutine_condition_wait (GCoroutine *coroutine,
+ GConditionWaitFunc func, gpointer data);
+void g_coroutine_condition_cancel(GCoroutine *coroutine);
-gboolean g_condition_wait (GConditionWaitFunc func, gpointer data);
void g_signal_emit_main_context(GObject *object, GSignalEmitMainFunc func,
int signum, gpointer params, const char *debug_info);
void g_object_notify_main_context(GObject *object, const gchar *property_name);
diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h
index 7fa005c..ebdc5ce 100644
--- a/gtk/spice-channel-priv.h
+++ b/gtk/spice-channel-priv.h
@@ -154,7 +154,7 @@ uint16_t spice_header_get_msg_type(uint8_t *header, gboolean is_mini_header);
uint32_t spice_header_get_msg_size(uint8_t *header, gboolean is_mini_header);
void spice_channel_up(SpiceChannel *channel);
-void spice_channel_wakeup(SpiceChannel *channel);
+void spice_channel_wakeup(SpiceChannel *channel, gboolean cancel);
SpiceSession* spice_channel_get_session(SpiceChannel *channel);
diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 806f37c..9316f90 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -650,7 +650,7 @@ static gboolean spice_channel_idle_wakeup(gpointer user_data)
{
SpiceChannel *channel = SPICE_CHANNEL(user_data);
- spice_channel_wakeup(channel);
+ spice_channel_wakeup(channel, FALSE);
g_object_unref(channel);
return FALSE;
@@ -674,7 +674,7 @@ void spice_msg_out_send(SpiceMsgOut *out)
g_timeout_add_full(G_PRIORITY_HIGH, 0, spice_channel_idle_wakeup,
g_object_ref(out->channel), NULL);
else
- spice_channel_wakeup(out->channel);
+ spice_channel_wakeup(out->channel, FALSE);
}
/* coroutine context */
@@ -1690,11 +1690,14 @@ error:
/* system context */
/* TODO: we currently flush/wakeup immediately all buffered messages */
G_GNUC_INTERNAL
-void spice_channel_wakeup(SpiceChannel *channel)
+void spice_channel_wakeup(SpiceChannel *channel, gboolean cancel)
{
- SpiceChannelPrivate *c = channel->priv;
+ GCoroutine *c = &channel->priv->coroutine;
+
+ if (cancel)
+ g_coroutine_condition_cancel(c);
- g_coroutine_wakeup(&c->coroutine);
+ g_coroutine_wakeup(c);
}
G_GNUC_INTERNAL
@@ -1996,7 +1999,7 @@ static gboolean spice_channel_iterate(SpiceChannel *channel)
do {
/* freeze coroutine */
if (c->state == SPICE_CHANNEL_STATE_MIGRATING)
- g_condition_wait(wait_migration, channel);
+ g_coroutine_condition_wait(&c->coroutine, wait_migration, channel);
if (c->has_error) {
SPICE_DEBUG("channel has error, breaking loop");
@@ -2407,7 +2410,7 @@ void spice_channel_disconnect(SpiceChannel *channel, SpiceChannelEvent reason)
if (c->state == SPICE_CHANNEL_STATE_MIGRATING) {
c->state = SPICE_CHANNEL_STATE_READY;
} else
- spice_channel_wakeup(channel);
+ spice_channel_wakeup(channel, TRUE);
if (reason != SPICE_CHANNEL_NONE)
g_signal_emit(G_OBJECT(channel), signals[SPICE_CHANNEL_EVENT], 0, reason);
commit 348acdb3ad40282b9675b4706298df31d60ac11d
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Mon Jan 9 14:35:40 2012 +0100
Remove the non-interruptible version g_io_wait()
Use the common g_coroutine_socket_wait()
https://bugs.freedesktop.org/show_bug.cgi?id=44570
diff --git a/gtk/gio-coroutine.c b/gtk/gio-coroutine.c
index 704b5ac..806dad9 100644
--- a/gtk/gio-coroutine.c
+++ b/gtk/gio-coroutine.c
@@ -29,6 +29,11 @@ typedef struct _GConditionWaitSource
gpointer data;
} GConditionWaitSource;
+GCoroutine* g_coroutine_self(void)
+{
+ return (GCoroutine*)coroutine_self();
+}
+
/* Main loop helper functions */
static gboolean g_io_wait_helper(GSocket *sock G_GNUC_UNUSED,
GIOCondition cond,
@@ -39,52 +44,38 @@ static gboolean g_io_wait_helper(GSocket *sock G_GNUC_UNUSED,
return FALSE;
}
-GIOCondition g_io_wait(GSocket *sock, GIOCondition cond)
-{
- GIOCondition *ret;
- GSource *src = g_socket_create_source(sock,
- cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- NULL);
- g_source_set_callback(src, (GSourceFunc)g_io_wait_helper, coroutine_self(), NULL);
- g_source_attach(src, NULL);
- ret = coroutine_yield(NULL);
- g_source_unref(src);
- return *ret;
-}
-
-
-GIOCondition g_io_wait_interruptible(GCoroutine *self,
+GIOCondition g_coroutine_socket_wait(GCoroutine *self,
GSocket *sock,
GIOCondition cond)
{
- GIOCondition *ret;
- gint id;
+ GIOCondition *ret, val = 0;
+ GSource *src;
g_return_val_if_fail(self != NULL, 0);
+ g_return_val_if_fail(self->wait_id == 0, 0);
g_return_val_if_fail(sock != NULL, 0);
- GSource *src = g_socket_create_source(sock,
- cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
- NULL);
+ src = g_socket_create_source(sock, cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL, NULL);
g_source_set_callback(src, (GSourceFunc)g_io_wait_helper, self, NULL);
- id = g_source_attach(src, NULL);
- self->waiting = TRUE;
+ self->wait_id = g_source_attach(src, NULL);
ret = coroutine_yield(NULL);
- self->waiting = FALSE;
g_source_unref(src);
- if (ret == NULL) {
- g_source_remove(id);
- return 0;
- } else
- return *ret;
+ if (ret != NULL)
+ val = *ret;
+ else
+ g_source_remove(self->wait_id);
+
+ self->wait_id = 0;
+ return val;
}
-void g_io_wakeup(GCoroutine *coroutine)
+void g_coroutine_wakeup(GCoroutine *coroutine)
{
g_return_if_fail(coroutine != NULL);
+ g_return_if_fail(coroutine != g_coroutine_self());
- if (coroutine->waiting)
+ if (coroutine->wait_id)
coroutine_yieldto(&coroutine->coroutine, NULL);
}
diff --git a/gtk/gio-coroutine.h b/gtk/gio-coroutine.h
index 43dbc55..cb96a52 100644
--- a/gtk/gio-coroutine.h
+++ b/gtk/gio-coroutine.h
@@ -31,7 +31,7 @@ typedef struct _GCoroutine GCoroutine;
struct _GCoroutine
{
struct coroutine coroutine;
- gboolean waiting;
+ guint wait_id;
};
/*
@@ -47,10 +47,11 @@ typedef gboolean (*GConditionWaitFunc)(gpointer);
typedef void (*GSignalEmitMainFunc)(GObject *object, int signum, gpointer params);
-GIOCondition g_io_wait (GSocket *sock, GIOCondition cond);
+GCoroutine* g_coroutine_self (void);
+void g_coroutine_wakeup (GCoroutine *coroutine);
+GIOCondition g_coroutine_socket_wait(GCoroutine *coroutine, GSocket *sock, GIOCondition cond);
+
gboolean g_condition_wait (GConditionWaitFunc func, gpointer data);
-void g_io_wakeup (GCoroutine *coroutine);
-GIOCondition g_io_wait_interruptible(GCoroutine *coroutine, GSocket *sock, GIOCondition cond);
void g_signal_emit_main_context(GObject *object, GSignalEmitMainFunc func,
int signum, gpointer params, const char *debug_info);
void g_object_notify_main_context(GObject *object, const gchar *property_name);
diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 5f698b9..806f37c 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -755,7 +755,7 @@ static void spice_channel_flush_wire(SpiceChannel *channel,
}
if (ret == -1) {
if (cond != 0) {
- g_io_wait(c->sock, cond);
+ g_coroutine_socket_wait(&c->coroutine, c->sock, cond);
continue;
} else {
SPICE_DEBUG("Closing the channel: spice_channel_flush %d", errno);
@@ -883,7 +883,7 @@ reread:
if (ret == -1) {
if (cond != 0) {
- g_io_wait(c->sock, cond);
+ g_coroutine_socket_wait(&c->coroutine, c->sock, cond);
goto reread;
} else {
c->has_error = TRUE;
@@ -1694,7 +1694,7 @@ void spice_channel_wakeup(SpiceChannel *channel)
{
SpiceChannelPrivate *c = channel->priv;
- g_io_wakeup(&c->coroutine);
+ g_coroutine_wakeup(&c->coroutine);
}
G_GNUC_INTERNAL
@@ -2004,7 +2004,7 @@ static gboolean spice_channel_iterate(SpiceChannel *channel)
}
SPICE_CHANNEL_GET_CLASS(channel)->iterate_write(channel);
- ret = g_io_wait_interruptible(&c->coroutine, c->sock, G_IO_IN);
+ ret = g_coroutine_socket_wait(&c->coroutine, c->sock, G_IO_IN);
#ifdef WIN32
/* FIXME: windows gsocket is buggy, it doesn't return correct condition... */
@@ -2075,7 +2075,7 @@ static void *spice_channel_coroutine(void *data)
}
reconnect:
- c->sock = spice_session_channel_open_host(c->session, c->tls);
+ c->sock = spice_session_channel_open_host(c->session, channel, c->tls);
if (c->sock == NULL) {
if (!c->tls) {
SPICE_DEBUG("connection failed, trying with TLS port");
@@ -2154,7 +2154,7 @@ ssl_reconnect:
if (rc <= 0) {
rc = SSL_get_error(c->ssl, rc);
if (rc == SSL_ERROR_WANT_READ || rc == SSL_ERROR_WANT_WRITE) {
- g_io_wait(c->sock, G_IO_OUT|G_IO_ERR|G_IO_HUP);
+ g_coroutine_socket_wait(&c->coroutine, c->sock, G_IO_OUT|G_IO_ERR|G_IO_HUP);
goto ssl_reconnect;
} else {
g_warning("%s: SSL_connect: %s",
diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h
index bb5ae9b..5df1182 100644
--- a/gtk/spice-session-priv.h
+++ b/gtk/spice-session-priv.h
@@ -97,7 +97,8 @@ void spice_session_set_connection_id(SpiceSession *session, int id);
int spice_session_get_connection_id(SpiceSession *session);
gboolean spice_session_get_client_provided_socket(SpiceSession *session);
-GSocket* spice_session_channel_open_host(SpiceSession *session, gboolean use_tls);
+GSocket* spice_session_channel_open_host(SpiceSession *session, SpiceChannel *channel,
+ gboolean use_tls);
void spice_session_channel_new(SpiceSession *session, SpiceChannel *channel);
void spice_session_channel_destroy(SpiceSession *session, SpiceChannel *channel);
void spice_session_channel_migrate(SpiceSession *session, SpiceChannel *channel);
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index 614cf02..79ba1b6 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -1359,9 +1359,11 @@ gboolean spice_session_has_channel_type(SpiceSession *session, gint type)
/* ------------------------------------------------------------------ */
/* private functions */
-static GSocket *channel_connect_socket(GSocketAddress *sockaddr,
+static GSocket *channel_connect_socket(SpiceChannel *channel,
+ GSocketAddress *sockaddr,
GError **error)
{
+ SpiceChannelPrivate *c = channel->priv;
GSocket *sock = g_socket_new(g_socket_address_get_family(sockaddr),
G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_DEFAULT,
@@ -1375,7 +1377,7 @@ static GSocket *channel_connect_socket(GSocketAddress *sockaddr,
if (*error && (*error)->code == G_IO_ERROR_PENDING) {
g_clear_error(error);
SPICE_DEBUG("Socket pending");
- g_io_wait(sock, G_IO_OUT | G_IO_ERR | G_IO_HUP);
+ g_coroutine_socket_wait(&c->coroutine, sock, G_IO_OUT | G_IO_ERR | G_IO_HUP);
if (!g_socket_check_connect_result(sock, error)) {
SPICE_DEBUG("Failed to connect %s", (*error)->message);
@@ -1394,8 +1396,10 @@ static GSocket *channel_connect_socket(GSocketAddress *sockaddr,
return sock;
}
+/* coroutine context */
G_GNUC_INTERNAL
-GSocket* spice_session_channel_open_host(SpiceSession *session, gboolean use_tls)
+GSocket* spice_session_channel_open_host(SpiceSession *session, SpiceChannel *channel,
+ gboolean use_tls)
{
SpiceSessionPrivate *s = SPICE_SESSION_GET_PRIVATE(session);
GSocketConnectable *addr;
@@ -1425,7 +1429,7 @@ GSocket* spice_session_channel_open_host(SpiceSession *session, gboolean use_tls
(sockaddr = g_socket_address_enumerator_next(enumerator, NULL, &conn_error))) {
SPICE_DEBUG("Trying one socket");
g_clear_error(&conn_error);
- sock = channel_connect_socket(sockaddr, &conn_error);
+ sock = channel_connect_socket(channel, sockaddr, &conn_error);
if (conn_error != NULL)
SPICE_DEBUG("%s", conn_error->message);
g_object_unref(sockaddr);
commit 24187e7179c7bf37187b0c06e85fa867810fa00a
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Mon Jan 9 14:23:21 2012 +0100
Create a GCoroutine, get rid of wait_queue
https://bugs.freedesktop.org/show_bug.cgi?id=44570
diff --git a/gtk/gio-coroutine.c b/gtk/gio-coroutine.c
index 5c9621d..704b5ac 100644
--- a/gtk/gio-coroutine.c
+++ b/gtk/gio-coroutine.c
@@ -53,26 +53,24 @@ GIOCondition g_io_wait(GSocket *sock, GIOCondition cond)
}
-GIOCondition g_io_wait_interruptible(struct wait_queue *wait,
+GIOCondition g_io_wait_interruptible(GCoroutine *self,
GSocket *sock,
GIOCondition cond)
{
GIOCondition *ret;
gint id;
- g_return_val_if_fail(wait != NULL, 0);
+ g_return_val_if_fail(self != NULL, 0);
g_return_val_if_fail(sock != NULL, 0);
- wait->context = coroutine_self();
GSource *src = g_socket_create_source(sock,
cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
NULL);
- g_source_set_callback(src, (GSourceFunc)g_io_wait_helper,
- wait->context, NULL);
+ g_source_set_callback(src, (GSourceFunc)g_io_wait_helper, self, NULL);
id = g_source_attach(src, NULL);
- wait->waiting = TRUE;
+ self->waiting = TRUE;
ret = coroutine_yield(NULL);
- wait->waiting = FALSE;
+ self->waiting = FALSE;
g_source_unref(src);
if (ret == NULL) {
@@ -82,10 +80,12 @@ GIOCondition g_io_wait_interruptible(struct wait_queue *wait,
return *ret;
}
-void g_io_wakeup(struct wait_queue *wait)
+void g_io_wakeup(GCoroutine *coroutine)
{
- if (wait->waiting)
- coroutine_yieldto(wait->context, NULL);
+ g_return_if_fail(coroutine != NULL);
+
+ if (coroutine->waiting)
+ coroutine_yieldto(&coroutine->coroutine, NULL);
}
@@ -124,8 +124,8 @@ GSourceFuncs waitFuncs = {
static gboolean g_condition_wait_helper(gpointer data)
{
- struct coroutine *co = (struct coroutine *)data;
- coroutine_yieldto(co, NULL);
+ GCoroutine *self = (GCoroutine *)data;
+ coroutine_yieldto(&self->coroutine, NULL);
return FALSE;
}
diff --git a/gtk/gio-coroutine.h b/gtk/gio-coroutine.h
index 26e447e..43dbc55 100644
--- a/gtk/gio-coroutine.h
+++ b/gtk/gio-coroutine.h
@@ -26,10 +26,12 @@
G_BEGIN_DECLS
-struct wait_queue
+typedef struct _GCoroutine GCoroutine;
+
+struct _GCoroutine
{
+ struct coroutine coroutine;
gboolean waiting;
- struct coroutine *context;
};
/*
@@ -47,8 +49,8 @@ typedef void (*GSignalEmitMainFunc)(GObject *object, int signum, gpointer params
GIOCondition g_io_wait (GSocket *sock, GIOCondition cond);
gboolean g_condition_wait (GConditionWaitFunc func, gpointer data);
-void g_io_wakeup (struct wait_queue *wait);
-GIOCondition g_io_wait_interruptible(struct wait_queue *wait, GSocket *sock, GIOCondition cond);
+void g_io_wakeup (GCoroutine *coroutine);
+GIOCondition g_io_wait_interruptible(GCoroutine *coroutine, GSocket *sock, GIOCondition cond);
void g_signal_emit_main_context(GObject *object, GSignalEmitMainFunc func,
int signum, gpointer params, const char *debug_info);
void g_object_notify_main_context(GObject *object, const gchar *property_name);
diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h
index a3d1cd2..7fa005c 100644
--- a/gtk/spice-channel-priv.h
+++ b/gtk/spice-channel-priv.h
@@ -94,12 +94,11 @@ struct _SpiceChannelPrivate {
/* not swapped */
SpiceSession *session;
- struct coroutine coroutine;
+ GCoroutine coroutine;
int fd;
gboolean has_error;
guint connect_delayed_id;
- struct wait_queue wait;
GQueue xmit_queue;
gboolean xmit_queue_blocked;
GStaticMutex xmit_queue_lock;
diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 71c671e..5f698b9 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -1694,7 +1694,7 @@ void spice_channel_wakeup(SpiceChannel *channel)
{
SpiceChannelPrivate *c = channel->priv;
- g_io_wakeup(&c->wait);
+ g_io_wakeup(&c->coroutine);
}
G_GNUC_INTERNAL
@@ -2004,7 +2004,7 @@ static gboolean spice_channel_iterate(SpiceChannel *channel)
}
SPICE_CHANNEL_GET_CLASS(channel)->iterate_write(channel);
- ret = g_io_wait_interruptible(&c->wait, c->sock, G_IO_IN);
+ ret = g_io_wait_interruptible(&c->coroutine, c->sock, G_IO_IN);
#ifdef WIN32
/* FIXME: windows gsocket is buggy, it doesn't return correct condition... */
@@ -2042,7 +2042,7 @@ static gboolean spice_channel_delayed_unref(gpointer data)
g_return_val_if_fail(channel != NULL, FALSE);
SPICE_DEBUG("Delayed unref channel %s %p", c->name, channel);
- g_return_val_if_fail(c->coroutine.exited == TRUE, FALSE);
+ g_return_val_if_fail(c->coroutine.coroutine.exited == TRUE, FALSE);
g_object_unref(G_OBJECT(data));
@@ -2209,7 +2209,7 @@ static gboolean connect_delayed(gpointer data)
SPICE_DEBUG("Open coroutine starting %p", channel);
c->connect_delayed_id = 0;
- co = &c->coroutine;
+ co = &c->coroutine.coroutine;
co->stack_size = 16 << 20; /* 16Mb */
co->entry = spice_channel_coroutine;
commit 2126a03a8f70b5f3748d8d954d38aa1955f068b6
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Mon Jan 9 13:06:37 2012 +0100
Hide g_condition_wait_source, use GLib style convention
https://bugs.freedesktop.org/show_bug.cgi?id=44570
diff --git a/gtk/gio-coroutine.c b/gtk/gio-coroutine.c
index 7470b43..5c9621d 100644
--- a/gtk/gio-coroutine.c
+++ b/gtk/gio-coroutine.c
@@ -21,6 +21,14 @@
#include "gio-coroutine.h"
+typedef struct _GConditionWaitSource
+{
+ GSource src;
+ struct coroutine *co;
+ GConditionWaitFunc func;
+ gpointer data;
+} GConditionWaitSource;
+
/* Main loop helper functions */
static gboolean g_io_wait_helper(GSocket *sock G_GNUC_UNUSED,
GIOCondition cond,
@@ -87,7 +95,7 @@ void g_io_wakeup(struct wait_queue *wait)
*/
static gboolean g_condition_wait_prepare(GSource *src,
int *timeout) {
- struct g_condition_wait_source *vsrc = (struct g_condition_wait_source *)src;
+ GConditionWaitSource *vsrc = (GConditionWaitSource *)src;
*timeout = -1;
return vsrc->func(vsrc->data);
}
@@ -98,7 +106,7 @@ static gboolean g_condition_wait_prepare(GSource *src,
*/
static gboolean g_condition_wait_check(GSource *src)
{
- struct g_condition_wait_source *vsrc = (struct g_condition_wait_source *)src;
+ GConditionWaitSource *vsrc = (GConditionWaitSource *)src;
return vsrc->func(vsrc->data);
}
@@ -121,10 +129,10 @@ static gboolean g_condition_wait_helper(gpointer data)
return FALSE;
}
-gboolean g_condition_wait(g_condition_wait_func func, gpointer data)
+gboolean g_condition_wait(GConditionWaitFunc func, gpointer data)
{
GSource *src;
- struct g_condition_wait_source *vsrc;
+ GConditionWaitSource *vsrc;
/* Short-circuit check in case we've got it ahead of time */
if (func(data)) {
@@ -135,8 +143,8 @@ gboolean g_condition_wait(g_condition_wait_func func, gpointer data)
* Don't have it, so yield to the main loop, checking the condition
* on each iteration of the main loop
*/
- src = g_source_new(&waitFuncs, sizeof(struct g_condition_wait_source));
- vsrc = (struct g_condition_wait_source *)src;
+ src = g_source_new(&waitFuncs, sizeof(GConditionWaitSource));
+ vsrc = (GConditionWaitSource *)src;
vsrc->func = func;
vsrc->data = data;
diff --git a/gtk/gio-coroutine.h b/gtk/gio-coroutine.h
index 56a87e1..26e447e 100644
--- a/gtk/gio-coroutine.h
+++ b/gtk/gio-coroutine.h
@@ -41,20 +41,12 @@ struct wait_queue
* to busy wait on a timeout, since our condition is only checked
* when some other source's state changes
*/
-typedef gboolean (*g_condition_wait_func)(gpointer);
-
-struct g_condition_wait_source
-{
- GSource src;
- struct coroutine *co;
- g_condition_wait_func func;
- gpointer data;
-};
+typedef gboolean (*GConditionWaitFunc)(gpointer);
typedef void (*GSignalEmitMainFunc)(GObject *object, int signum, gpointer params);
GIOCondition g_io_wait (GSocket *sock, GIOCondition cond);
-gboolean g_condition_wait (g_condition_wait_func func, gpointer data);
+gboolean g_condition_wait (GConditionWaitFunc func, gpointer data);
void g_io_wakeup (struct wait_queue *wait);
GIOCondition g_io_wait_interruptible(struct wait_queue *wait, GSocket *sock, GIOCondition cond);
void g_signal_emit_main_context(GObject *object, GSignalEmitMainFunc func,
commit f37f7819eeeaf9c144cc0eef250c9475db8f94ce
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Thu Jan 12 18:57:56 2012 +0100
Lower connection error from warning to debug, it's normal to fail
We try several connections, so it's normal to fail for some.
No need to warn.
https://bugs.freedesktop.org/show_bug.cgi?id=44570
diff --git a/gtk/spice-session.c b/gtk/spice-session.c
index ef4f3c1..614cf02 100644
--- a/gtk/spice-session.c
+++ b/gtk/spice-session.c
@@ -1427,7 +1427,7 @@ GSocket* spice_session_channel_open_host(SpiceSession *session, gboolean use_tls
g_clear_error(&conn_error);
sock = channel_connect_socket(sockaddr, &conn_error);
if (conn_error != NULL)
- g_warning("%s", conn_error->message);
+ SPICE_DEBUG("%s", conn_error->message);
g_object_unref(sockaddr);
}
g_object_unref(enumerator);
More information about the Spice-commits
mailing list