[Spice-devel] [RFCv5 18/47] server/red_channel: introduce pipes functions

Alon Levy alevy at redhat.com
Sun May 8 06:11:14 PDT 2011


Introduce functions to add (via producer method) the same item to multiple
pipes, all for the same channel.

Note: Right now there is only a single channel, but the next patches will do the
per-channel breakdown to channel and channel_client before actually introducing
a ring in RedChannel, this makes it easier to make smaller changes - the
channel->rcc link will exist until removed in the ring introducing patch.
---
 server/red_channel.c |   59 ++++++++++++++++++++++++++++++++++++++++++++++---
 server/red_channel.h |   18 +++++++++++---
 2 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/server/red_channel.c b/server/red_channel.c
index 6733e52..c36ab3b 100644
--- a/server/red_channel.c
+++ b/server/red_channel.c
@@ -904,17 +904,17 @@ int red_channel_all_clients_serials_are_zero(RedChannel *channel)
     return (!channel->rcc || channel->rcc->send_data.serial == 0);
 }
 
-void red_channel_apply_clients(RedChannel *channel, channel_client_visitor v)
+void red_channel_apply_clients(RedChannel *channel, channel_client_callback cb)
 {
     if (channel->rcc) {
-        v(channel->rcc);
+        cb(channel->rcc);
     }
 }
 
-void red_channel_apply_clients_data(RedChannel *channel, channel_client_visitor_data v, void *data)
+void red_channel_apply_clients_data(RedChannel *channel, channel_client_callback_data cb, void *data)
 {
     if (channel->rcc) {
-        v(channel->rcc, data);
+        cb(channel->rcc, data);
     }
 }
 
@@ -1069,3 +1069,54 @@ MainChannelClient *red_client_get_main(RedClient *client) {
 void red_client_set_main(RedClient *client, MainChannelClient *mcc) {
     client->mcc = mcc;
 }
+
+/*
+ * Functions to push the same item to multiple pipes.
+ */
+
+/*
+ * TODO: after convinced of correctness, add paths for single client
+ * that avoid the whole loop. perhaps even have a function pointer table
+ * later.
+ * TODO - inline? macro? right now this is the simplest from code amount
+ */
+
+typedef void (*rcc_item_t)(RedChannelClient *rcc, PipeItem *item);
+typedef int (*rcc_item_cond_t)(RedChannelClient *rcc, PipeItem *item);
+
+static void red_channel_pipes_create_batch(RedChannel *channel,
+                                new_pipe_item_t creator, void *data,
+                                rcc_item_t callback)
+{
+    RedChannelClient *rcc;
+    PipeItem *item;
+    int num = 0;
+
+    if (!(rcc = channel->rcc)) {
+        return;
+    }
+    item = (*creator)(rcc, data, num++);
+    if (callback) {
+        (*callback)(rcc, item);
+    }
+}
+
+void red_channel_pipes_new_add_push(RedChannel *channel,
+                              new_pipe_item_t creator, void *data)
+{
+    red_channel_pipes_create_batch(channel, creator, data,
+                                     red_channel_client_pipe_add);
+    red_channel_push(channel);
+}
+
+void red_channel_pipes_new_add(RedChannel *channel, new_pipe_item_t creator, void *data)
+{
+    red_channel_pipes_create_batch(channel, creator, data,
+                                     red_channel_client_pipe_add);
+}
+
+void red_channel_pipes_new_add_tail(RedChannel *channel, new_pipe_item_t creator, void *data)
+{
+    red_channel_pipes_create_batch(channel, creator, data,
+                                     red_channel_client_pipe_add_tail_no_push);
+}
diff --git a/server/red_channel.h b/server/red_channel.h
index 09a613a..f11565b 100644
--- a/server/red_channel.h
+++ b/server/red_channel.h
@@ -270,6 +270,16 @@ void red_channel_client_set_message_serial(RedChannelClient *channel, uint64_t);
 void red_channel_client_begin_send_message(RedChannelClient *rcc);
 
 void red_channel_pipe_item_init(RedChannel *channel, PipeItem *item, int type);
+
+// TODO: add back the channel_pipe_add functionality - by adding reference counting
+// to the PipeItem.
+
+// helper to push a new item to all channels
+typedef PipeItem *(*new_pipe_item_t)(RedChannelClient *rcc, void *data, int num);
+void red_channel_pipes_new_add_push(RedChannel *channel, new_pipe_item_t creator, void *data);
+void red_channel_pipes_new_add(RedChannel *channel, new_pipe_item_t creator, void *data);
+void red_channel_pipes_new_add_tail(RedChannel *channel, new_pipe_item_t creator, void *data);
+
 void red_channel_client_pipe_add_push(RedChannelClient *rcc, PipeItem *item);
 void red_channel_client_pipe_add(RedChannelClient *rcc, PipeItem *item);
 void red_channel_client_pipe_add_after(RedChannelClient *rcc, PipeItem *item, PipeItem *pos);
@@ -358,10 +368,10 @@ RedClient *red_channel_client_get_client(RedChannelClient *rcc);
 SpiceDataHeader *red_channel_client_get_header(RedChannelClient *rcc);
 
 /* apply given function to all connected clients */
-typedef void (*channel_client_visitor)(RedChannelClient *rcc);
-typedef void (*channel_client_visitor_data)(RedChannelClient *rcc, void *data);
-void red_channel_apply_clients(RedChannel *channel, channel_client_visitor v);
-void red_channel_apply_clients_data(RedChannel *channel, channel_client_visitor_data v, void *data);
+typedef void (*channel_client_callback)(RedChannelClient *rcc);
+typedef void (*channel_client_callback_data)(RedChannelClient *rcc, void *data);
+void red_channel_apply_clients(RedChannel *channel, channel_client_callback v);
+void red_channel_apply_clients_data(RedChannel *channel, channel_client_callback_data v, void *data);
 
 struct RedClient {
     RingItem link;
-- 
1.7.5.1



More information about the Spice-devel mailing list