diff options
author | Alon Levy <alevy@redhat.com> | 2011-04-11 21:44:16 +0300 |
---|---|---|
committer | Alon Levy <alevy@redhat.com> | 2011-08-23 17:58:46 +0300 |
commit | 0f0bdb190b8586ef7ac20fcefffe641e44eb15b9 (patch) | |
tree | c60604668c0c1290f7a1d640c1ed5c65ea5d46b7 /server | |
parent | 03cf66383ca9393e6521b96289a53dfc9d7cab60 (diff) | |
download | spice-0f0bdb190b8586ef7ac20fcefffe641e44eb15b9.tar.gz spice-0f0bdb190b8586ef7ac20fcefffe641e44eb15b9.tar.xz spice-0f0bdb190b8586ef7ac20fcefffe641e44eb15b9.zip |
server/red_channel: introduce pipes functions
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.
Diffstat (limited to 'server')
-rw-r--r-- | server/red_channel.c | 59 | ||||
-rw-r--r-- | 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 a6fee999..f084dbef 100644 --- a/server/red_channel.c +++ b/server/red_channel.c @@ -906,17 +906,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); } } @@ -1071,3 +1071,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 09a613ae..f11565b6 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; |