[Spice-devel] [PATCH spice-gtk 1/3] channel: add flush_async()
Hans de Goede
hdegoede at redhat.com
Sun Dec 2 03:13:03 PST 2012
Hi,
Looks good to me, ACK series
Regards,
Hans
On 11/30/2012 01:43 PM, Marc-André Lureau wrote:
> Add spice_channel_flush_async() that asynchronously will write all the
> pending channel data.
> ---
> doc/reference/spice-gtk-sections.txt | 2 +
> gtk/map-file | 2 +
> gtk/spice-channel-priv.h | 1 +
> gtk/spice-channel.c | 100 +++++++++++++++++++++++++++++++++++
> gtk/spice-channel.h | 4 +-
> 5 files changed, 108 insertions(+), 1 deletion(-)
>
> diff --git a/doc/reference/spice-gtk-sections.txt b/doc/reference/spice-gtk-sections.txt
> index 60e287a..87d4225 100644
> --- a/doc/reference/spice-gtk-sections.txt
> +++ b/doc/reference/spice-gtk-sections.txt
> @@ -99,6 +99,8 @@ spice_channel_test_capability
> spice_channel_test_common_capability
> spice_channel_type_to_string
> spice_channel_set_capability
> +spice_channel_flush_async
> +spice_channel_flush_finish
> <SUBSECTION Standard>
> SPICE_TYPE_CHANNEL_EVENT
> spice_channel_event_get_type
> diff --git a/gtk/map-file b/gtk/map-file
> index ed2c07f..79ad9d2 100644
> --- a/gtk/map-file
> +++ b/gtk/map-file
> @@ -14,6 +14,8 @@ spice_channel_set_capability;
> spice_channel_test_capability;
> spice_channel_test_common_capability;
> spice_channel_type_to_string;
> +spice_channel_flush_async;
> +spice_channel_flush_finish;
> spice_client_error_quark;
> spice_cursor_channel_get_type;
> spice_display_channel_get_type;
> diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h
> index a769ef8..41a1b34 100644
> --- a/gtk/spice-channel-priv.h
> +++ b/gtk/spice-channel-priv.h
> @@ -134,6 +134,7 @@ struct _SpiceChannelPrivate {
>
> gsize total_read_bytes;
> uint64_t last_message_serial;
> + GSList *flushing;
> };
>
> SpiceMsgIn *spice_msg_in_new(SpiceChannel *channel);
> diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
> index 06667d4..c9c4639 100644
> --- a/gtk/spice-channel.c
> +++ b/gtk/spice-channel.c
> @@ -1971,6 +1971,22 @@ void spice_channel_destroy(SpiceChannel *channel)
> g_object_unref(channel);
> }
>
> +/* any context */
> +static void spice_channel_flushed(SpiceChannel *channel, gboolean success)
> +{
> + SpiceChannelPrivate *c = channel->priv;
> + GSList *l;
> +
> + for (l = c->flushing; l != NULL; l = l->next) {
> + GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT(l->data);
> + g_simple_async_result_set_op_res_gboolean(result, success);
> + g_simple_async_result_complete_in_idle(result);
> + }
> +
> + g_slist_free_full(c->flushing, g_object_unref);
> + c->flushing = NULL;
> +}
> +
> /* coroutine context */
> static void spice_channel_iterate_write(SpiceChannel *channel)
> {
> @@ -1984,6 +2000,8 @@ static void spice_channel_iterate_write(SpiceChannel *channel)
> if (out)
> spice_channel_write_msg(channel, out);
> } while (out);
> +
> + spice_channel_flushed(channel, TRUE);
> }
>
> /* coroutine context */
> @@ -2444,6 +2462,7 @@ static void channel_reset(SpiceChannel *channel, gboolean migrating)
>
> STATIC_MUTEX_LOCK(c->xmit_queue_lock);
> c->xmit_queue_blocked = TRUE; /* Disallow queuing new messages */
> + gboolean was_empty = g_queue_is_empty(&c->xmit_queue);
> g_queue_foreach(&c->xmit_queue, (GFunc)spice_msg_out_unref, NULL);
> g_queue_clear(&c->xmit_queue);
> if (c->xmit_queue_wakeup_id) {
> @@ -2451,6 +2470,7 @@ static void channel_reset(SpiceChannel *channel, gboolean migrating)
> c->xmit_queue_wakeup_id = 0;
> }
> STATIC_MUTEX_UNLOCK(c->xmit_queue_lock);
> + spice_channel_flushed(channel, was_empty);
>
> g_array_set_size(c->remote_common_caps, 0);
> g_array_set_size(c->remote_caps, 0);
> @@ -2722,3 +2742,83 @@ static void spice_channel_send_migration_handshake(SpiceChannel *channel)
> c->state = SPICE_CHANNEL_STATE_MIGRATING;
> }
> }
> +
> +/**
> + * spice_channel_flush_async:
> + * @channel: a #SpiceChannel
> + * @cancellable: (allow-none): optional GCancellable object, %NULL to ignore
> + * @callback: (scope async): callback to call when the request is satisfied
> + * @user_data: (closure): the data to pass to callback function
> + *
> + * Forces an asynchronous write of all user-space buffered data for
> + * the given channel.
> + *
> + * When the operation is finished callback will be called. You can
> + * then call spice_channel_flush_finish() to get the result of the
> + * operation.
> + *
> + * Since: 0.15
> + **/
> +void spice_channel_flush_async(SpiceChannel *self, GCancellable *cancellable,
> + GAsyncReadyCallback callback, gpointer user_data)
> +{
> + GSimpleAsyncResult *simple;
> + SpiceChannelPrivate *c;
> + gboolean was_empty;
> +
> + g_return_if_fail(SPICE_IS_CHANNEL(self));
> + c = self->priv;
> +
> + if (!c->state == SPICE_CHANNEL_STATE_READY) {
> + g_simple_async_report_error_in_idle(G_OBJECT(self), callback, user_data,
> + SPICE_CLIENT_ERROR, SPICE_CLIENT_ERROR_FAILED,
> + "The channel is not ready yet");
> + return;
> + }
> +
> + simple = g_simple_async_result_new(G_OBJECT(self), callback, user_data,
> + spice_channel_flush_async);
> +
> + STATIC_MUTEX_LOCK(c->xmit_queue_lock);
> + was_empty = g_queue_is_empty(&c->xmit_queue);
> + STATIC_MUTEX_UNLOCK(c->xmit_queue_lock);
> + if (was_empty) {
> + g_simple_async_result_set_op_res_gboolean(simple, TRUE);
> + g_simple_async_result_complete_in_idle(simple);
> + return;
> + }
> +
> + c->flushing = g_slist_append(c->flushing, simple);
> +}
> +
> +/**
> + * spice_channel_flush_finish:
> + * @channel: a #SpiceChannel
> + * @result: a #GAsyncResult
> + * @error: a #GError location to store the error occurring, or %NULL
> + * to ignore.
> + *
> + * Finishes flushing a channel.
> + *
> + * Returns: %TRUE if flush operation succeeded, %FALSE otherwise.
> + * Since: 0.15
> + **/
> +gboolean spice_channel_flush_finish(SpiceChannel *self, GAsyncResult *result,
> + GError **error)
> +{
> + GSimpleAsyncResult *simple;
> +
> + g_return_val_if_fail(SPICE_IS_CHANNEL(self), FALSE);
> + g_return_val_if_fail(result != NULL, FALSE);
> +
> + simple = (GSimpleAsyncResult *)result;
> +
> + if (g_simple_async_result_propagate_error(simple, error))
> + return -1;
> +
> + g_return_val_if_fail(g_simple_async_result_is_valid(result, G_OBJECT(self),
> + spice_channel_flush_async), FALSE);
> +
> + CHANNEL_DEBUG(self, "flushed finished!");
> + return g_simple_async_result_get_op_res_gboolean(simple);
> +}
> diff --git a/gtk/spice-channel.h b/gtk/spice-channel.h
> index d40b844..52ecd97 100644
> --- a/gtk/spice-channel.h
> +++ b/gtk/spice-channel.h
> @@ -20,6 +20,7 @@
>
> G_BEGIN_DECLS
>
> +#include <gio/gio.h>
> #include "spice-types.h"
> #include "spice-glib-enums.h"
> #include "spice-util.h"
> @@ -112,7 +113,8 @@ gboolean spice_channel_open_fd(SpiceChannel *channel, int fd);
> void spice_channel_disconnect(SpiceChannel *channel, SpiceChannelEvent reason);
> gboolean spice_channel_test_capability(SpiceChannel *channel, guint32 cap);
> gboolean spice_channel_test_common_capability(SpiceChannel *channel, guint32 cap);
> -
> +void spice_channel_flush_async(SpiceChannel *channel, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
> +gboolean spice_channel_flush_finish(SpiceChannel *channel, GAsyncResult *result, GError **error);
> #ifndef SPICE_DISABLE_DEPRECATED
> SPICE_DEPRECATED
> void spice_channel_set_capability(SpiceChannel *channel, guint32 cap);
>
More information about the Spice-devel
mailing list