[Spice-devel] [PATCH spice-gtk 3/6] spice-channel: replace the xmit buf by a queue of SpiceOutMsg-s
Hans de Goede
hdegoede at redhat.com
Thu Dec 1 07:48:53 PST 2011
This has a number of advantages:
-It significantly simplifies the code
-It avoids memcpy-ing all the write data one more time
-It avoids malloc / realloc / free of the xmit buffer
(this gets replaced by gslice alloc / free for the queue elements)
Signed-off-by: Hans de Goede <hdegoede at redhat.com>
---
gtk/spice-channel-priv.h | 4 +-
gtk/spice-channel.c | 99 +++++++++++++++------------------------------
2 files changed, 34 insertions(+), 69 deletions(-)
diff --git a/gtk/spice-channel-priv.h b/gtk/spice-channel-priv.h
index 8aa0e7c..ed5f3a7 100644
--- a/gtk/spice-channel-priv.h
+++ b/gtk/spice-channel-priv.h
@@ -94,9 +94,7 @@ struct _SpiceChannelPrivate {
guint connect_delayed_id;
struct wait_queue wait;
- guint8 *xmit_buffer;
- int xmit_buffer_capacity;
- int xmit_buffer_size;
+ GQueue xmit_queue;
char name[16];
enum spice_channel_state state;
diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 9e2aee0..5e5f351 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -104,6 +104,7 @@ static void spice_channel_init(SpiceChannel *channel)
c->remote_caps = g_array_new(FALSE, TRUE, sizeof(guint32));
c->remote_common_caps = g_array_new(FALSE, TRUE, sizeof(guint32));
spice_channel_set_common_capability(channel, SPICE_COMMON_CAP_PROTOCOL_AUTH_SELECTION);
+ g_queue_init(&c->xmit_queue);
}
static void spice_channel_constructed(GObject *gobject)
@@ -682,6 +683,25 @@ static void spice_channel_write(SpiceChannel *channel, const void *data, size_t
spice_channel_flush_wire(channel, data, len);
}
+/* coroutine context */
+static void spice_channel_write_msg(SpiceChannel *channel, SpiceMsgOut *out)
+{
+ uint8_t *data;
+ int free_data;
+ size_t len;
+
+ g_return_if_fail(channel != NULL);
+ g_return_if_fail(out != NULL);
+ g_return_if_fail(channel == out->channel);
+
+ data = spice_marshaller_linearize(out->marshaller, 0, &len, &free_data);
+ /* spice_msg_out_hexdump(out, data, len); */
+ spice_channel_write(channel, data, len);
+
+ if (free_data)
+ free(data);
+}
+
/*
* Read at least 1 more byte of data straight off the wire
* into the requested buffer.
@@ -1526,25 +1546,6 @@ error:
}
/* system context */
-static void spice_channel_buffered_write(SpiceChannel *channel, const void *data, size_t size)
-{
- SpiceChannelPrivate *c = channel->priv;
- size_t left;
-
- left = c->xmit_buffer_capacity - c->xmit_buffer_size;
- if (left < size) {
- c->xmit_buffer_capacity += size + 4095;
- c->xmit_buffer_capacity &= ~4095;
-
- c->xmit_buffer = g_realloc(c->xmit_buffer, c->xmit_buffer_capacity);
- }
-
- memcpy(&c->xmit_buffer[c->xmit_buffer_size], data, size);
-
- c->xmit_buffer_size += size;
-}
-
-/* system context */
/* TODO: we currently flush/wakeup immediately all buffered messages */
G_GNUC_INTERNAL
void spice_channel_wakeup(SpiceChannel *channel)
@@ -1564,9 +1565,7 @@ gboolean spice_channel_get_read_only(SpiceChannel *channel)
system context if @buffered is TRUE */
static void spice_channel_send_msg(SpiceChannel *channel, SpiceMsgOut *out, gboolean buffered)
{
- uint8_t *data;
- int free_data;
- size_t len;
+ SpiceChannelPrivate *c = channel->priv;
g_return_if_fail(channel != NULL);
g_return_if_fail(out != NULL);
@@ -1577,16 +1576,12 @@ static void spice_channel_send_msg(SpiceChannel *channel, SpiceMsgOut *out, gboo
return;
}
- data = spice_marshaller_linearize(out->marshaller, 0,
- &len, &free_data);
- /* spice_msg_out_hexdump(out, data, len); */
- if (buffered)
- spice_channel_buffered_write(channel, data, len);
- else
- spice_channel_write(channel, data, len);
-
- if (free_data)
- free(data);
+ if (buffered) {
+ spice_msg_out_ref(out);
+ g_queue_push_tail(&c->xmit_queue, out);
+ } else {
+ spice_channel_write_msg(channel, out);
+ }
}
/* coroutine context */
@@ -1804,35 +1799,11 @@ void spice_channel_destroy(SpiceChannel *channel)
static void spice_channel_iterate_write(SpiceChannel *channel)
{
SpiceChannelPrivate *c = channel->priv;
+ SpiceMsgOut *out;
- while (c->xmit_buffer_size) {
- /*
- * Take ownership of the buffer, so that if spice_channel_write calls
- * g_io_wait and thus yields to the main context, and that then calls
- * spice_channel_buffered_write it does not mess with the buffer
- * being written out.
- */
- guint8 *buffer = c->xmit_buffer;
- int size = c->xmit_buffer_size;
- int capacity = c->xmit_buffer_capacity;
-
- c->xmit_buffer = NULL;
- c->xmit_buffer_size = 0;
- c->xmit_buffer_capacity = 0;
-
- spice_channel_write(channel, buffer, size);
-
- /*
- * If no write has been done in the mean time, we can return the buffer
- * so that it can be re-used.
- */
- if (c->xmit_buffer == NULL) {
- c->xmit_buffer = buffer;
- c->xmit_buffer_capacity = capacity;
- c->xmit_buffer_size = 0;
- } else {
- g_free(buffer);
- }
+ while ((out = g_queue_pop_head(&c->xmit_queue))) {
+ spice_channel_write_msg(channel, out);
+ spice_msg_out_unref(out);
}
}
@@ -2213,12 +2184,8 @@ static void channel_disconnect(SpiceChannel *channel)
c->peer_msg = NULL;
c->peer_pos = 0;
- if (c->xmit_buffer) {
- g_free(c->xmit_buffer);
- c->xmit_buffer = NULL;
- c->xmit_buffer_size = 0;
- c->xmit_buffer_capacity = 0;
- }
+ g_queue_foreach(&c->xmit_queue, (GFunc)spice_msg_out_unref, NULL);
+ g_queue_clear(&c->xmit_queue);
g_array_set_size(c->remote_common_caps, 0);
g_array_set_size(c->remote_caps, 0);
--
1.7.7.4
More information about the Spice-devel
mailing list