From cb698c5734adf60683b6c64034159c26c444b9c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 4 Jan 2012 15:06:13 +0100 Subject: [PATCH spice-gtk] Implement SPICE_MSG_WAIT_FOR_CHANNELS https://bugs.freedesktop.org/show_bug.cgi?id=44179 --- gtk/channel-base.c | 39 ++++++++++++++++++++++++++++++++++++--- gtk/spice-channel-priv.h | 1 + gtk/spice-channel.c | 2 ++ gtk/spice-session-priv.h | 1 + gtk/spice-session.c | 11 +++++------ 5 files changed, 45 insertions(+), 9 deletions(-) diff --git a/gtk/channel-base.c b/gtk/channel-base.c index a6a2892..54232ef 100644 --- a/gtk/channel-base.c +++ b/gtk/channel-base.c @@ -90,14 +90,47 @@ void spice_channel_handle_disconnect(SpiceChannel *channel, SpiceMsgIn *in) disconnect->time_stamp, disconnect->reason); } +typedef struct WaitForChannelData +{ + SpiceWaitForChannel *wait; + SpiceChannel *channel; +} WaitForChannelData; + +/* coroutine and main context */ +static gboolean wait_for_channel(gpointer data) +{ + WaitForChannelData *wfc = data; + SpiceChannelPrivate *c = wfc->channel->priv; + SpiceChannel *wait_channel; + + wait_channel = spice_session_lookup_channel(c->session, wfc->wait->channel_id, wfc->wait->channel_type); + g_return_val_if_fail(wait_channel != NULL, TRUE); + + if (wait_channel->priv->last_message_serial >= wfc->wait->message_serial) + return TRUE; + + return FALSE; +} + /* coroutine context */ 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); */ + SpiceMsgWaitForChannels *wfc = spice_msg_in_parsed(in); + int i; + + g_return_if_fail(in->header.size >= sizeof(*wfc) + wfc->wait_count * sizeof(wfc->wait_list[0])); - SPICE_DEBUG("%s TODO", __FUNCTION__); + for (i = 0; i < wfc->wait_count; ++i) { + WaitForChannelData data = { + .wait = wfc->wait_list + i, + .channel = channel + }; + + SPICE_DEBUG("waiting for serial %lu (%d/%d)", data.wait->message_serial, i + 1, wfc->wait_count); + g_condition_wait(wait_for_channel, &data); + SPICE_DEBUG("waiting for serial %lu, done", data.wait->message_serial); + } } static void diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h index df35e4c..ea510c7 100644 --- a/gtk/spice-channel-priv.h +++ b/gtk/spice-channel-priv.h @@ -126,6 +126,7 @@ struct _SpiceChannelPrivate { GArray *remote_common_caps; gsize total_read_bytes; + uint64_t last_message_serial; }; SpiceMsgIn *spice_msg_in_new(SpiceChannel *channel); diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c index 079028a..04af87d 100644 --- a/gtk/spice-channel.c +++ b/gtk/spice-channel.c @@ -1680,6 +1680,8 @@ void spice_channel_recv_msg(SpiceChannel *channel, msg_handler(channel, in, data); end: + c->last_message_serial = in->header.serial; + /* release message */ c->msg_in = NULL; spice_msg_in_unref(in); diff --git a/gtk/spice-session-priv.h b/gtk/spice-session-priv.h index 4d52254..bb5ae9b 100644 --- a/gtk/spice-session-priv.h +++ b/gtk/spice-session-priv.h @@ -127,6 +127,7 @@ void spice_session_palettes_clear(SpiceSession *session); void spice_session_images_clear(SpiceSession *session); void spice_session_migrate_end(SpiceSession *session); gboolean spice_session_migrate_after_main_init(SpiceSession *session); +SpiceChannel* spice_session_lookup_channel(SpiceSession *session, gint id, gint type); G_END_DECLS diff --git a/gtk/spice-session.c b/gtk/spice-session.c index a2fa550..00057a0 100644 --- a/gtk/spice-session.c +++ b/gtk/spice-session.c @@ -1061,8 +1061,7 @@ void spice_session_set_migration(SpiceSession *session, SpiceSession *migration) } G_GNUC_INTERNAL -SpiceChannel* get_channel_by_id_and_type(SpiceSession *session, - gint id, gint type) +SpiceChannel* spice_session_lookup_channel(SpiceSession *session, gint id, gint type) { RingItem *ring, *next; SpiceSessionPrivate *s = session->priv; @@ -1107,9 +1106,9 @@ void spice_session_abort_migration(SpiceSession *session) continue; spice_channel_swap(c->channel, - get_channel_by_id_and_type(s->migration, - spice_channel_get_channel_id(c->channel), - spice_channel_get_channel_type(c->channel))); + spice_session_lookup_channel(s->migration, + spice_channel_get_channel_id(c->channel), + spice_channel_get_channel_type(c->channel))); } g_list_free(s->migration_left); @@ -1136,7 +1135,7 @@ void spice_session_channel_migrate(SpiceSession *session, SpiceChannel *channel) type = spice_channel_get_channel_type(channel); SPICE_DEBUG("migrating channel id:%d type:%d", id, type); - c = get_channel_by_id_and_type(s->migration, id, type); + c = spice_session_lookup_channel(s->migration, id, type); g_return_if_fail(c != NULL); spice_channel_swap(channel, c); -- 1.7.7.5