From 5b27e1b0b0b1be50caef3d3401b02b5f4b024a68 Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Mon, 11 Apr 2011 21:44:16 +0300 Subject: 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. --- server/red_channel.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ server/red_channel.h | 12 +++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/server/red_channel.c b/server/red_channel.c index aff99ed5..7e1edbea 100644 --- a/server/red_channel.c +++ b/server/red_channel.c @@ -1051,4 +1051,55 @@ 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); +void __red_channel_pipes_create_batch(RedChannel *channel, + new_pipe_item_t creator, void *data, + rcc_item_t visitor) +{ + RedChannelClient *rcc; + PipeItem *item; + int num = 0; + + if (!(rcc = channel->rcc)) { + return; + } + item = (*creator)(rcc, data, num++); + if (visitor) { + (*visitor)(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); +} + +// despite the name, this should push (TODO: match function to name) +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); + red_channel_push(channel); +} diff --git a/server/red_channel.h b/server/red_channel.h index 877c5679..15d70b68 100644 --- a/server/red_channel.h +++ b/server/red_channel.h @@ -271,6 +271,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); @@ -374,4 +384,4 @@ void red_client_destroy(RedClient *client); void red_client_set_main(RedClient *client, MainChannelClient *mcc); MainChannelClient *red_client_get_main(RedClient *client); -#endif +#endif \ No newline at end of file -- cgit v1.2.3