[Spice-devel] [PATCH 08/11] Replace RedChannel::clients with GList
Frediano Ziglio
fziglio at redhat.com
Fri May 13 14:24:31 UTC 2016
>
> Instead of using a Ring, use a GList to store the list of channel
> clients. This allows us to iterate the clients without poking inside of
> the client struct to get the channel_link. This is required in order to
> make the RedChannelClient struct private.
> ---
> server/display-channel.c | 64 ++++++++--------
> server/display-channel.h | 16 ++--
> server/main-channel.c | 42 +++++------
> server/red-channel.c | 193
> ++++++++++++++++++++---------------------------
> server/red-channel.h | 3 +-
> server/red-worker.c | 6 +-
> server/red-worker.h | 15 ++--
> server/stream.c | 23 +++---
> 8 files changed, 162 insertions(+), 200 deletions(-)
>
> diff --git a/server/display-channel.c b/server/display-channel.c
> index 1f4d66f..25d7a5b 100644
> --- a/server/display-channel.c
> +++ b/server/display-channel.c
> @@ -254,7 +254,7 @@ void display_channel_surface_unref(DisplayChannel
> *display, uint32_t surface_id)
> RedSurface *surface = &display->surfaces[surface_id];
> QXLInstance *qxl = display->common.qxl;
> DisplayChannelClient *dcc;
> - RingItem *link, *next;
> + GList *link, *next;
>
> if (--surface->refs != 0) {
> return;
> @@ -287,7 +287,7 @@ static void streams_update_visible_region(DisplayChannel
> *display, Drawable *dra
> {
> Ring *ring;
> RingItem *item;
> - RingItem *dcc_ring_item, *next;
> + GList *link, *next;
> DisplayChannelClient *dcc;
>
> if (!red_channel_is_connected(RED_CHANNEL(display))) {
> @@ -311,7 +311,7 @@ static void streams_update_visible_region(DisplayChannel
> *display, Drawable *dra
> continue;
> }
>
> - FOREACH_DCC(display, dcc_ring_item, next, dcc) {
> + FOREACH_DCC(display, link, next, dcc) {
> agent = &dcc->stream_agents[get_stream_id(display, stream)];
>
> if (region_intersects(&agent->vis_region,
> &drawable->tree_item.base.rgn)) {
> @@ -326,10 +326,10 @@ static void
> streams_update_visible_region(DisplayChannel *display, Drawable *dra
> static void pipes_add_drawable(DisplayChannel *display, Drawable *drawable)
> {
> DisplayChannelClient *dcc;
> - RingItem *dcc_ring_item, *next;
> + GList *link, *next;
>
> spice_warn_if_fail(ring_is_empty(&drawable->pipes));
> - FOREACH_DCC(display, dcc_ring_item, next, dcc) {
> + FOREACH_DCC(display, link, next, dcc) {
> dcc_prepend_drawable(dcc, drawable);
> }
> }
> @@ -351,9 +351,9 @@ static void pipes_add_drawable_after(DisplayChannel
> *display,
> return;
> }
> if (num_other_linked != display->common.base.clients_num) {
> - RingItem *item, *next;
> + GList *link, *next;
> spice_debug("TODO: not O(n^2)");
> - FOREACH_DCC(display, item, next, dcc) {
> + FOREACH_DCC(display, link, next, dcc) {
> int sent = 0;
> DRAWABLE_FOREACH_DPI_SAFE(pos_after, dpi_link, dpi_next,
> dpi_pos_after) {
> if (dpi_pos_after->dcc == dcc) {
> @@ -498,34 +498,32 @@ static int current_add_equal(DisplayChannel *display,
> DrawItem *item, TreeItem *
>
> DisplayChannelClient *dcc;
> RedDrawablePipeItem *dpi;
> - RingItem *worker_ring_item, *dpi_ring_item;
> + RingItem *dpi_ring_item;
> + GList *link;
>
> other_drawable->refs++;
> current_remove_drawable(display, other_drawable);
>
> /* sending the drawable to clients that already received
> * (or will receive) other_drawable */
> - worker_ring_item =
> ring_get_head(&RED_CHANNEL(display)->clients);
> + link = RED_CHANNEL(display)->clients;
> dpi_ring_item = ring_get_head(&other_drawable->pipes);
> /* dpi contains a sublist of dcc's, ordered the same */
> - while (worker_ring_item) {
> - dcc = SPICE_CONTAINEROF(worker_ring_item,
> DisplayChannelClient,
> - common.base.channel_link);
> + while (link) {
> + dcc = link->data;
> dpi = SPICE_CONTAINEROF(dpi_ring_item, RedDrawablePipeItem,
> base);
> - while (worker_ring_item && (!dpi || dcc != dpi->dcc)) {
> + while (link && (!dpi || dcc != dpi->dcc)) {
> dcc_prepend_drawable(dcc, drawable);
> - worker_ring_item =
> ring_next(&RED_CHANNEL(display)->clients,
> - worker_ring_item);
> - dcc = SPICE_CONTAINEROF(worker_ring_item,
> DisplayChannelClient,
> - common.base.channel_link);
> + link = link->next;
> + if (link)
> + dcc = link->data;
> }
>
> if (dpi_ring_item) {
> dpi_ring_item = ring_next(&other_drawable->pipes,
> dpi_ring_item);
> }
> - if (worker_ring_item) {
> - worker_ring_item =
> ring_next(&RED_CHANNEL(display)->clients,
> - worker_ring_item);
> + if (link) {
> + link = link->next;
> }
> }
> /* not sending other_drawable where possible */
> @@ -1200,9 +1198,9 @@ int
> display_channel_wait_for_migrate_data(DisplayChannel *display)
> }
>
> spice_debug(NULL);
> - spice_warn_if_fail(channel->clients_num == 1);
> + spice_warn_if_fail(g_list_length(channel->clients) == 1);
>
> - rcc = SPICE_CONTAINEROF(ring_get_head(&channel->clients),
> RedChannelClient, channel_link);
> + rcc = g_list_nth_data(channel->clients, 0);
>
> red_channel_client_ref(rcc);
> for (;;) {
> @@ -1239,24 +1237,24 @@ void
> display_channel_flush_all_surfaces(DisplayChannel *display)
>
> void display_channel_free_glz_drawables_to_free(DisplayChannel *display)
> {
> - RingItem *link, *next;
> + GList *link, *next;
> DisplayChannelClient *dcc;
>
> spice_return_if_fail(display);
>
> - DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display)) {
> + FOREACH_DCC(display, link, next, dcc) {
> dcc_free_glz_drawables_to_free(dcc);
> }
> }
>
> void display_channel_free_glz_drawables(DisplayChannel *display)
> {
> - RingItem *link, *next;
> + GList *link, *next;
> DisplayChannelClient *dcc;
>
> spice_return_if_fail(display);
>
> - DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display)) {
> + FOREACH_DCC(display, link, next, dcc) {
> dcc_free_glz_drawables(dcc);
> }
> }
> @@ -1299,11 +1297,11 @@ void display_channel_free_some(DisplayChannel
> *display)
> {
> int n = 0;
> DisplayChannelClient *dcc;
> - RingItem *item, *next;
> + GList *link, *next;
>
> spice_debug("#draw=%d, #glz_draw=%d", display->drawable_count,
> display->glz_drawable_count);
> - FOREACH_DCC(display, item, next, dcc) {
> + FOREACH_DCC(display, link, next, dcc) {
> GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL;
>
> if (glz_dict) {
> @@ -1318,7 +1316,7 @@ void display_channel_free_some(DisplayChannel *display)
> free_one_drawable(display, TRUE);
> }
>
> - FOREACH_DCC(display, item, next, dcc) {
> + FOREACH_DCC(display, link, next, dcc) {
> GlzSharedDictionary *glz_dict = dcc ? dcc->glz_dict : NULL;
>
> if (glz_dict) {
> @@ -1790,10 +1788,10 @@ void display_channel_update(DisplayChannel *display,
> static void clear_surface_drawables_from_pipes(DisplayChannel *display, int
> surface_id,
> int wait_if_used)
> {
> - RingItem *item, *next;
> + GList *link, *next;
> DisplayChannelClient *dcc;
>
> - FOREACH_DCC(display, item, next, dcc) {
> + FOREACH_DCC(display, link, next, dcc) {
> if (!dcc_clear_surface_drawables_from_pipe(dcc, surface_id,
> wait_if_used)) {
> red_channel_client_disconnect(RED_CHANNEL_CLIENT(dcc));
> }
> @@ -1857,9 +1855,9 @@ void display_channel_destroy_surfaces(DisplayChannel
> *display)
> static void send_create_surface(DisplayChannel *display, int surface_id, int
> image_ready)
> {
> DisplayChannelClient *dcc;
> - RingItem *item, *next;
> + GList *link, *next;
>
> - FOREACH_DCC(display, item, next, dcc) {
> + FOREACH_DCC(display, link, next, dcc) {
> dcc_create_surface(dcc, surface_id);
> if (image_ready)
> dcc_push_surface_image(dcc, surface_id);
> diff --git a/server/display-channel.h b/server/display-channel.h
> index 76668de..f61e38e 100644
> --- a/server/display-channel.h
> +++ b/server/display-channel.h
> @@ -226,14 +226,14 @@ struct DisplayChannel {
> stat_info_t lz4_stat;
> };
>
> -#define LINK_TO_DCC(ptr) SPICE_CONTAINEROF(ptr, DisplayChannelClient, \
> - common.base.channel_link)
> -#define DCC_FOREACH_SAFE(link, next, dcc, channel) \
> - SAFE_FOREACH(link, next, channel, &(channel)->clients, dcc,
> LINK_TO_DCC(link))
> -
> -
> -#define FOREACH_DCC(display_channel, link, next, dcc) \
> - DCC_FOREACH_SAFE(link, next, dcc, RED_CHANNEL(display_channel))
> +#define FOREACH_DCC(channel, _link, _next, _data) \
> + for (_link = (channel ? RED_CHANNEL(channel)->clients : NULL), \
> + _next = (_link ? _link->next : NULL), \
> + _data = (_link ? _link->data : NULL); \
> + _link; \
> + _link = _next, \
> + _next = (_link ? _link->next : NULL), \
> + _data = (_link ? _link->data : NULL))
>
so basically only one macro which is safe
> static inline int get_stream_id(DisplayChannel *display, Stream *stream)
> {
> diff --git a/server/main-channel.c b/server/main-channel.c
> index 4808658..2ae33e1 100644
> --- a/server/main-channel.c
> +++ b/server/main-channel.c
> @@ -42,12 +42,12 @@ static void
> main_channel_client_on_disconnect(RedChannelClient *rcc)
>
> RedClient *main_channel_get_client_by_link_id(MainChannel *main_chan,
> uint32_t connection_id)
> {
> - RingItem *link;
> + GList *link;
> MainChannelClient *mcc;
> RedChannelClient *rcc;
>
> - RING_FOREACH(link, &main_chan->base.clients) {
> - rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
> + for (link = main_chan->base.clients; link != NULL; link = link->next) {
> + rcc = link->data;
why the manual code here and not a macro ?
> mcc = (MainChannelClient*) rcc;
> if (main_channel_client_get_connection_id(mcc) == connection_id) {
> return rcc->client;
> @@ -334,11 +334,10 @@ MainChannel* main_channel_new(RedsState *reds)
>
> static int main_channel_connect_semi_seamless(MainChannel *main_channel)
> {
> - RingItem *client_link;
> + GList *link;
>
> - RING_FOREACH(client_link, &main_channel->base.clients) {
> - RedChannelClient *rcc = SPICE_CONTAINEROF(client_link,
> RedChannelClient,
> - channel_link);
> + for (link = main_channel->base.clients; link != NULL; link = link->next)
> {
> + RedChannelClient *rcc = link->data;
same here
> MainChannelClient *mcc = (MainChannelClient*)rcc;
> if (main_channel_client_connect_semi_seamless(mcc))
> main_channel->num_clients_mig_wait++;
> @@ -348,13 +347,12 @@ static int
> main_channel_connect_semi_seamless(MainChannel *main_channel)
>
> static int main_channel_connect_seamless(MainChannel *main_channel)
> {
> - RingItem *client_link;
> + GList *link;
>
> - spice_assert(main_channel->base.clients_num == 1);
> + spice_assert(g_list_length(main_channel->base.clients) == 1);
>
> - RING_FOREACH(client_link, &main_channel->base.clients) {
> - RedChannelClient *rcc = SPICE_CONTAINEROF(client_link,
> RedChannelClient,
> - channel_link);
> + for (link = main_channel->base.clients; link != NULL; link = link->next)
> {
> + RedChannelClient *rcc = link->data;
same
> MainChannelClient *mcc = (MainChannelClient*)rcc;
> main_channel_client_connect_seamless(mcc);
> main_channel->num_clients_mig_wait++;
> @@ -375,11 +373,9 @@ int main_channel_migrate_connect(MainChannel
> *main_channel, RedsMigSpice *mig_ta
> if (!try_seamless) {
> return main_channel_connect_semi_seamless(main_channel);
> } else {
> - RingItem *client_item;
> RedChannelClient *rcc;
>
> - client_item = ring_get_head(&main_channel->base.clients);
> - rcc = SPICE_CONTAINEROF(client_item, RedChannelClient,
> channel_link);
> + rcc = g_list_nth_data(main_channel->base.clients, 0);
>
> if (!red_channel_client_test_remote_cap(rcc,
> SPICE_MAIN_CAP_SEAMLESS_MIGRATE))
> {
> @@ -393,11 +389,10 @@ int main_channel_migrate_connect(MainChannel
> *main_channel, RedsMigSpice *mig_ta
>
> void main_channel_migrate_cancel_wait(MainChannel *main_chan)
> {
> - RingItem *client_link;
> + GList *link;
>
> - RING_FOREACH(client_link, &main_chan->base.clients) {
> - RedChannelClient *rcc = SPICE_CONTAINEROF(client_link,
> RedChannelClient,
> - channel_link);
> + for (link = main_chan->base.clients; link != NULL; link = link->next) {
> + RedChannelClient *rcc = link->data;
> MainChannelClient *mcc = (MainChannelClient*)rcc;
> main_channel_client_migrate_cancel_wait(mcc);
> }
> @@ -406,19 +401,18 @@ void main_channel_migrate_cancel_wait(MainChannel
> *main_chan)
>
> int main_channel_migrate_src_complete(MainChannel *main_chan, int success)
> {
> - RingItem *client_link;
> + GList *link;
> int semi_seamless_count = 0;
>
> spice_printerr("");
>
> - if (ring_is_empty(&main_chan->base.clients)) {
> + if (!main_chan->base.clients) {
> spice_printerr("no peer connected");
> return 0;
> }
>
> - RING_FOREACH(client_link, &main_chan->base.clients) {
> - RedChannelClient *rcc = SPICE_CONTAINEROF(client_link,
> RedChannelClient,
> - channel_link);
> + for (link = main_chan->base.clients; link != NULL; link = link->next) {
> + RedChannelClient *rcc = link->data;
> MainChannelClient *mcc = (MainChannelClient*)rcc;
> if (main_channel_client_migrate_src_complete(mcc, success))
> semi_seamless_count++;
> diff --git a/server/red-channel.c b/server/red-channel.c
> index c88828c..0d402e3 100644
> --- a/server/red-channel.c
> +++ b/server/red-channel.c
> @@ -327,14 +327,7 @@ void red_channel_client_receive(RedChannelClient *rcc)
>
> void red_channel_receive(RedChannel *channel)
> {
> - RingItem *link;
> - RingItem *next;
> - RedChannelClient *rcc;
> -
> - RING_FOREACH_SAFE(link, next, &channel->clients) {
> - rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
> - red_channel_client_receive(rcc);
> - }
> + g_list_foreach(channel->clients, (GFunc)red_channel_client_receive,
> NULL);
> }
>
> static void red_peer_handle_outgoing(RedsStream *stream, OutgoingHandler
> *handler)
> @@ -652,8 +645,7 @@ static void
> red_channel_client_pipe_remove(RedChannelClient *rcc, RedPipeItem *i
> static void red_channel_add_client(RedChannel *channel, RedChannelClient
> *rcc)
> {
> spice_assert(rcc);
> - ring_add(&channel->clients, &rcc->channel_link);
> - channel->clients_num++;
> + channel->clients = g_list_append(channel->clients, rcc);
> }
>
> static void red_channel_client_set_remote_caps(RedChannelClient* rcc,
> @@ -691,10 +683,10 @@ int red_channel_client_test_remote_cap(RedChannelClient
> *rcc, uint32_t cap)
>
> int red_channel_test_remote_common_cap(RedChannel *channel, uint32_t cap)
> {
> - RingItem *link;
> + GList *link;
>
> - RING_FOREACH(link, &channel->clients) {
> - RedChannelClient *rcc = SPICE_CONTAINEROF(link, RedChannelClient,
> channel_link);
> + for (link = channel->clients; link != NULL; link = link->next) {
> + RedChannelClient *rcc = link->data;
>
> if (!red_channel_client_test_remote_common_cap(rcc, cap)) {
> return FALSE;
> @@ -705,10 +697,10 @@ int red_channel_test_remote_common_cap(RedChannel
> *channel, uint32_t cap)
>
> int red_channel_test_remote_cap(RedChannel *channel, uint32_t cap)
> {
> - RingItem *link;
> + GList *link;
>
> - RING_FOREACH(link, &channel->clients) {
> - RedChannelClient *rcc = SPICE_CONTAINEROF(link, RedChannelClient,
> channel_link);
> + for (link = channel->clients; link != NULL; link = link->next) {
> + RedChannelClient *rcc = link->data;
>
> if (!red_channel_client_test_remote_cap(rcc, cap)) {
> return FALSE;
> @@ -916,7 +908,7 @@ RedChannelClient *red_channel_client_create(int size,
> RedChannel *channel, RedCl
> stream->socket,
> SPICE_WATCH_EVENT_READ,
> red_channel_client_event, rcc);
> - rcc->id = channel->clients_num;
> + rcc->id = g_list_length(channel->clients);
> red_channel_add_client(channel, rcc);
> red_client_add_channel(client, rcc);
> red_channel_ref(channel);
> @@ -985,16 +977,17 @@ int
> red_channel_client_is_waiting_for_migrate_data(RedChannelClient *rcc)
> int red_channel_is_waiting_for_migrate_data(RedChannel *channel)
> {
> RedChannelClient *rcc;
> + guint n_clients = g_list_length(channel->clients);
>
> if (!red_channel_is_connected(channel)) {
> return FALSE;
> }
>
> - if (channel->clients_num > 1) {
> + if (n_clients > 1) {
> return FALSE;
> }
> - spice_assert(channel->clients_num == 1);
> - rcc = SPICE_CONTAINEROF(ring_get_head(&channel->clients),
> RedChannelClient, channel_link);
> + spice_assert(n_clients == 1);
> + rcc = g_list_nth_data(channel->clients, 0);
> return red_channel_client_is_waiting_for_migrate_data(rcc);
> }
>
> @@ -1053,7 +1046,6 @@ RedChannel *red_channel_create(int size,
>
> channel->reds = reds;
> channel->core = core;
> - ring_init(&channel->clients);
>
> // TODO: send incoming_cb as parameters instead of duplicating?
> channel->incoming_cb.alloc_msg_buf =
> (alloc_msg_recv_buf_proc)channel_cbs->alloc_recv_buf;
> @@ -1120,7 +1112,6 @@ RedChannel *red_channel_create_dummy(int size,
> RedsState *reds, uint32_t type, u
> channel->refs = 1;
> channel->reds = reds;
> channel->core = &dummy_core;
> - ring_init(&channel->clients);
> client_cbs.connect = red_channel_client_default_connect;
> client_cbs.disconnect = red_channel_client_default_disconnect;
> client_cbs.migrate = red_channel_client_default_migrate;
> @@ -1287,17 +1278,11 @@ void red_channel_client_destroy(RedChannelClient
> *rcc)
>
> void red_channel_destroy(RedChannel *channel)
> {
> - RingItem *link;
> - RingItem *next;
> -
> if (!channel) {
> return;
> }
> - RING_FOREACH_SAFE(link, next, &channel->clients) {
> - red_channel_client_destroy(
> - SPICE_CONTAINEROF(link, RedChannelClient, channel_link));
> - }
>
> + g_list_foreach(channel->clients, (GFunc)red_channel_client_destroy,
> NULL);
> red_channel_unref(channel);
> }
>
> @@ -1320,12 +1305,7 @@ void red_channel_client_send(RedChannelClient *rcc)
>
> void red_channel_send(RedChannel *channel)
> {
> - RingItem *link;
> - RingItem *next;
> -
> - RING_FOREACH_SAFE(link, next, &channel->clients) {
> - red_channel_client_send(SPICE_CONTAINEROF(link, RedChannelClient,
> channel_link));
> - }
> + g_list_foreach(channel->clients, (GFunc)red_channel_client_send, NULL);
> }
>
> static inline int red_channel_client_waiting_for_ack(RedChannelClient *rcc)
> @@ -1380,17 +1360,11 @@ void red_channel_client_push(RedChannelClient *rcc)
>
> void red_channel_push(RedChannel *channel)
> {
> - RingItem *link;
> - RingItem *next;
> - RedChannelClient *rcc;
> -
> if (!channel) {
> return;
> }
> - RING_FOREACH_SAFE(link, next, &channel->clients) {
> - rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
> - red_channel_client_push(rcc);
> - }
> +
> + g_list_foreach(channel->clients, (GFunc)red_channel_client_push, NULL);
> }
>
> int red_channel_client_get_roundtrip_ms(RedChannelClient *rcc)
> @@ -1411,13 +1385,7 @@ static void
> red_channel_client_init_outgoing_messages_window(RedChannelClient *r
> // specific
> void red_channel_init_outgoing_messages_window(RedChannel *channel)
> {
> - RingItem *link;
> - RingItem *next;
> -
> - RING_FOREACH_SAFE(link, next, &channel->clients) {
> - red_channel_client_init_outgoing_messages_window(
> - SPICE_CONTAINEROF(link, RedChannelClient, channel_link));
> - }
> + g_list_foreach(channel->clients,
> (GFunc)red_channel_client_init_outgoing_messages_window, NULL);
> }
>
> static void red_channel_handle_migrate_flush_mark(RedChannelClient *rcc)
> @@ -1734,15 +1702,16 @@ void
> red_channel_client_pipe_add_type(RedChannelClient *rcc, int pipe_item_type)
> red_channel_client_push(rcc);
> }
>
> -void red_channel_pipes_add_type(RedChannel *channel, int pipe_item_type)
> +static void red_channel_client_pipe_add_type_proxy(gpointer data, gpointer
> user_data)
> {
> - RingItem *link, *next;
> + int type = GPOINTER_TO_INT(user_data);
> + red_channel_client_pipe_add_type(data, type);
> +}
>
> - RING_FOREACH_SAFE(link, next, &channel->clients) {
> - red_channel_client_pipe_add_type(
> - SPICE_CONTAINEROF(link, RedChannelClient, channel_link),
> - pipe_item_type);
> - }
> +void red_channel_pipes_add_type(RedChannel *channel, int pipe_item_type)
> +{
> + g_list_foreach(channel->clients, red_channel_client_pipe_add_type_proxy,
> + GINT_TO_POINTER(pipe_item_type));
> }
>
> void red_channel_client_pipe_add_empty_msg(RedChannelClient *rcc, int
> msg_type)
> @@ -1755,21 +1724,22 @@ void
> red_channel_client_pipe_add_empty_msg(RedChannelClient *rcc, int msg_type)
> red_channel_client_push(rcc);
> }
>
> -void red_channel_pipes_add_empty_msg(RedChannel *channel, int msg_type)
> +static void red_channel_client_pipe_add_empty_msg_proxy(gpointer data,
> gpointer user_data)
> {
> - RingItem *link, *next;
> + int type = GPOINTER_TO_INT(user_data);
> + red_channel_client_pipe_add_empty_msg(data, type);
> +}
>
> - RING_FOREACH_SAFE(link, next, &channel->clients) {
> - red_channel_client_pipe_add_empty_msg(
> - SPICE_CONTAINEROF(link, RedChannelClient, channel_link),
> - msg_type);
> - }
> +void red_channel_pipes_add_empty_msg(RedChannel *channel, int msg_type)
> +{
> + g_list_foreach(channel->clients,
> red_channel_client_pipe_add_empty_msg_proxy, GINT_TO_POINTER(msg_type));
> }
>
> int red_channel_client_is_connected(RedChannelClient *rcc)
> {
> if (!rcc->dummy) {
> - return ring_item_is_linked(&rcc->channel_link);
> + return rcc->channel
> + && (g_list_find(rcc->channel->clients, rcc) != NULL);
> } else {
> return rcc->dummy_connected;
> }
> @@ -1777,7 +1747,7 @@ int red_channel_client_is_connected(RedChannelClient
> *rcc)
>
> int red_channel_is_connected(RedChannel *channel)
> {
> - return channel && (channel->clients_num > 0);
> + return channel && channel->clients;
> }
>
> void red_channel_client_clear_sent_item(RedChannelClient *rcc)
> @@ -1816,6 +1786,8 @@ void
> red_channel_client_ack_set_client_window(RedChannelClient *rcc, int client_
>
> static void red_channel_remove_client(RedChannelClient *rcc)
> {
> + GList *link;
> +
> if (!pthread_equal(pthread_self(), rcc->channel->thread_id)) {
> spice_warning("channel type %d id %d - "
> "channel->thread_id (0x%lx) != pthread_self (0x%lx)."
> @@ -1824,11 +1796,11 @@ static void
> red_channel_remove_client(RedChannelClient *rcc)
> rcc->channel->type, rcc->channel->id,
> rcc->channel->thread_id, pthread_self());
> }
> - spice_return_if_fail(ring_item_is_linked(&rcc->channel_link));
> + spice_return_if_fail(rcc->channel);
> + link = g_list_find(rcc->channel->clients, rcc);
> + spice_return_if_fail(link != NULL);
>
> - ring_remove(&rcc->channel_link);
> - spice_assert(rcc->channel->clients_num > 0);
> - rcc->channel->clients_num--;
> + rcc->channel->clients = g_list_remove_link(rcc->channel->clients, link);
> // TODO: should we set rcc->channel to NULL???
> }
>
> @@ -1842,11 +1814,12 @@ static void
> red_client_remove_channel(RedChannelClient *rcc)
>
> static void red_channel_client_disconnect_dummy(RedChannelClient *rcc)
> {
> + GList *link;
> spice_assert(rcc->dummy);
> - if (ring_item_is_linked(&rcc->channel_link)) {
> + if (rcc->channel && (link = g_list_find(rcc->channel->clients, rcc))) {
> spice_printerr("rcc=%p (channel=%p type=%d id=%d)", rcc,
> rcc->channel,
> rcc->channel->type, rcc->channel->id);
> - red_channel_remove_client(rcc);
> + red_channel_remove_client(link->data);
> }
> rcc->dummy_connected = FALSE;
> }
> @@ -1881,13 +1854,7 @@ void red_channel_client_disconnect(RedChannelClient
> *rcc)
>
> void red_channel_disconnect(RedChannel *channel)
> {
> - RingItem *link;
> - RingItem *next;
> -
> - RING_FOREACH_SAFE(link, next, &channel->clients) {
> - red_channel_client_disconnect(
> - SPICE_CONTAINEROF(link, RedChannelClient, channel_link));
> - }
> + g_list_foreach(channel->clients, (GFunc)red_channel_client_disconnect,
> NULL);
> }
>
> RedChannelClient *red_channel_client_create_dummy(int size,
> @@ -1937,26 +1904,24 @@ error:
>
> void red_channel_apply_clients(RedChannel *channel, channel_client_callback
> cb)
> {
> - RingItem *link;
> - RingItem *next;
> - RedChannelClient *rcc;
> + g_list_foreach(channel->clients, (GFunc)cb, NULL);
> +}
>
> - RING_FOREACH_SAFE(link, next, &channel->clients) {
> - rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
> - cb(rcc);
> - }
> +void red_channel_apply_clients_data(RedChannel *channel,
> channel_client_callback_data cb, void *data)
> +{
> + g_list_foreach(channel->clients, (GFunc)cb, data);
> }
>
> int red_channel_all_blocked(RedChannel *channel)
> {
> - RingItem *link;
> + GList *link;
> RedChannelClient *rcc;
>
> - if (!channel || channel->clients_num == 0) {
> + if (!channel || !channel->clients) {
> return FALSE;
> }
> - RING_FOREACH(link, &channel->clients) {
> - rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
> + for (link = channel->clients; link != NULL; link = link->next) {
> + rcc = link->data;
> if (!rcc->send_data.blocked) {
> return FALSE;
> }
> @@ -1966,11 +1931,11 @@ int red_channel_all_blocked(RedChannel *channel)
>
> int red_channel_any_blocked(RedChannel *channel)
> {
> - RingItem *link;
> + GList *link;
> RedChannelClient *rcc;
>
> - RING_FOREACH(link, &channel->clients) {
> - rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
> + for (link = channel->clients; link != NULL; link = link->next) {
> + rcc = link->data;
> if (rcc->send_data.blocked) {
> return TRUE;
> }
> @@ -2013,20 +1978,23 @@ void
> red_channel_client_set_header_sub_list(RedChannelClient *rcc, uint32_t sub_
>
> int red_channel_get_first_socket(RedChannel *channel)
> {
> - if (!channel || channel->clients_num == 0) {
> + RedChannelClient *rcc;
> +
> + if (!channel || !channel->clients) {
> return -1;
> }
> - return SPICE_CONTAINEROF(ring_get_head(&channel->clients),
> - RedChannelClient,
> channel_link)->stream->socket;
> + rcc = g_list_nth_data(channel->clients, 0);
> +
> + return rcc->stream->socket;
> }
>
> int red_channel_no_item_being_sent(RedChannel *channel)
> {
> - RingItem *link;
> + GList *link;
> RedChannelClient *rcc;
>
> - RING_FOREACH(link, &channel->clients) {
> - rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
> + for (link = channel->clients; link != NULL; link = link->next) {
> + rcc = link->data;
> if (!red_channel_client_no_item_being_sent(rcc)) {
> return FALSE;
> }
> @@ -2263,7 +2231,7 @@ static int red_channel_pipes_create_batch(RedChannel
> *channel,
> new_pipe_item_t creator, void *data,
> rcc_item_t pipe_add)
> {
> - RingItem *link, *next;
> + GList *link, *next;
> RedChannelClient *rcc;
> RedPipeItem *item;
> int num = 0, n = 0;
> @@ -2271,13 +2239,16 @@ static int red_channel_pipes_create_batch(RedChannel
> *channel,
> spice_assert(creator != NULL);
> spice_assert(pipe_add != NULL);
>
> - RING_FOREACH_SAFE(link, next, &channel->clients) {
> - rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
> + link = channel->clients;
> + while (link != NULL) {
> + next = link->next;
> + rcc = link->data;
> item = (*creator)(rcc, data, num++);
> if (item) {
> (*pipe_add)(rcc, item);
> n++;
> }
> + link = next;
> }
>
> return n;
> @@ -2307,12 +2278,12 @@ void red_channel_pipes_new_add_tail(RedChannel
> *channel, new_pipe_item_t creator
>
> uint32_t red_channel_max_pipe_size(RedChannel *channel)
> {
> - RingItem *link;
> + GList *link;
> RedChannelClient *rcc;
> uint32_t pipe_size = 0;
>
> - RING_FOREACH(link, &channel->clients) {
> - rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
> + for (link = channel->clients; link != NULL; link = link->next) {
> + rcc = link->data;
> pipe_size = MAX(pipe_size, rcc->pipe_size);
> }
> return pipe_size;
> @@ -2320,12 +2291,12 @@ uint32_t red_channel_max_pipe_size(RedChannel
> *channel)
>
> uint32_t red_channel_min_pipe_size(RedChannel *channel)
> {
> - RingItem *link;
> + GList *link;
> RedChannelClient *rcc;
> uint32_t pipe_size = ~0;
>
> - RING_FOREACH(link, &channel->clients) {
> - rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
> + for (link = channel->clients; link != NULL; link = link->next) {
> + rcc = link->data;
> pipe_size = MIN(pipe_size, rcc->pipe_size);
> }
> return pipe_size == ~0 ? 0 : pipe_size;
> @@ -2333,12 +2304,12 @@ uint32_t red_channel_min_pipe_size(RedChannel
> *channel)
>
> uint32_t red_channel_sum_pipes_size(RedChannel *channel)
> {
> - RingItem *link;
> + GList *link;
> RedChannelClient *rcc;
> uint32_t sum = 0;
>
> - RING_FOREACH(link, &channel->clients) {
> - rcc = SPICE_CONTAINEROF(link, RedChannelClient, channel_link);
> + for (link = channel->clients; link != NULL; link = link->next) {
> + rcc = link->data;
> sum += rcc->pipe_size;
> }
> return sum;
> diff --git a/server/red-channel.h b/server/red-channel.h
> index 03e6407..f5aeea7 100644
> --- a/server/red-channel.h
> +++ b/server/red-channel.h
> @@ -311,7 +311,7 @@ struct RedChannel {
> // However RCC still holds a reference to the Channel.
> // Maybe replace these logic with ref count?
> // TODO: rename to 'connected_clients'?
> - Ring clients;
> + GList *clients;
> uint32_t clients_num;
>
> OutgoingHandlerInterface outgoing_cb;
> @@ -552,6 +552,7 @@ uint32_t red_channel_sum_pipes_size(RedChannel *channel);
> 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 RedsState* red_channel_get_server(RedChannel *channel);
>
> struct RedClient {
> diff --git a/server/red-worker.c b/server/red-worker.c
> index 8d8073e..86f1645 100644
> --- a/server/red-worker.c
> +++ b/server/red-worker.c
> @@ -500,7 +500,7 @@ static void guest_set_client_capabilities(RedWorker
> *worker)
> int i;
> DisplayChannelClient *dcc;
> RedChannelClient *rcc;
> - RingItem *link, *next;
> + GList *link, *next;
> uint8_t caps[SPICE_CAPABILITIES_SIZE] = { 0 };
> int caps_available[] = {
> SPICE_DISPLAY_CAP_SIZED_STREAM,
> @@ -533,7 +533,7 @@ static void guest_set_client_capabilities(RedWorker
> *worker)
> for (i = 0 ; i < sizeof(caps_available) / sizeof(caps_available[0]);
> ++i) {
> SET_CAP(caps, caps_available[i]);
> }
> - DCC_FOREACH_SAFE(link, next, dcc,
> RED_CHANNEL(worker->display_channel)) {
> + FOREACH_DCC(worker->display_channel, link, next, dcc) {
> rcc = (RedChannelClient *)dcc;
> for (i = 0 ; i < sizeof(caps_available) /
> sizeof(caps_available[0]); ++i) {
> if (!red_channel_client_test_remote_cap(rcc,
> caps_available[i]))
> @@ -646,7 +646,7 @@ static void display_update_monitors_config(DisplayChannel
> *display,
> static void red_worker_push_monitors_config(RedWorker *worker)
> {
> DisplayChannelClient *dcc;
> - RingItem *item, *next;
> + GList *item, *next;
>
> FOREACH_DCC(worker->display_channel, item, next, dcc) {
> dcc_push_monitors_config(dcc);
> diff --git a/server/red-worker.h b/server/red-worker.h
> index d7525e0..63be8b5 100644
> --- a/server/red-worker.h
> +++ b/server/red-worker.h
> @@ -75,19 +75,16 @@ static inline void red_pipe_add_verb(RedChannelClient*
> rcc, uint16_t verb)
> red_channel_client_pipe_add(rcc, &item->base);
> }
>
> -#define LINK_TO_RCC(ptr) SPICE_CONTAINEROF(ptr, RedChannelClient,
> channel_link)
> -#define RCC_FOREACH_SAFE(link, next, rcc, channel) \
> - SAFE_FOREACH(link, next, channel, &(channel)->clients, rcc,
> LINK_TO_RCC(link))
> +static inline void red_pipe_add_verb_proxy(RedChannelClient *rcc, gpointer
> data)
> +{
> + uint16_t verb = GPOINTER_TO_UINT(data);
> + red_pipe_add_verb(rcc, verb);
> +}
>
>
> static inline void red_pipes_add_verb(RedChannel *channel, uint16_t verb)
> {
> - RedChannelClient *rcc;
> - RingItem *link, *next;
> -
> - RCC_FOREACH_SAFE(link, next, rcc, channel) {
> - red_pipe_add_verb(rcc, verb);
> - }
> + red_channel_apply_clients_data(channel, red_pipe_add_verb_proxy,
> GUINT_TO_POINTER(verb));
> }
>
> RedWorker* red_worker_new(QXLInstance *qxl,
> diff --git a/server/stream.c b/server/stream.c
> index 8884480..2c2613f 100644
> --- a/server/stream.c
> +++ b/server/stream.c
> @@ -66,13 +66,13 @@ void stream_agent_stats_print(StreamAgent *agent)
> void stream_stop(DisplayChannel *display, Stream *stream)
> {
> DisplayChannelClient *dcc;
> - RingItem *item, *next;
> + GList *link, *next;
>
> spice_return_if_fail(ring_item_is_linked(&stream->link));
> spice_return_if_fail(!stream->current);
>
> spice_debug("stream %d", get_stream_id(display, stream));
> - FOREACH_DCC(display, item, next, dcc) {
> + FOREACH_DCC(display, link, next, dcc) {
> StreamAgent *stream_agent;
>
> stream_agent = &dcc->stream_agents[get_stream_id(display, stream)];
> @@ -260,7 +260,7 @@ static int is_next_stream_frame(DisplayChannel *display,
> static void attach_stream(DisplayChannel *display, Drawable *drawable,
> Stream *stream)
> {
> DisplayChannelClient *dcc;
> - RingItem *item, *next;
> + GList *link, *next;
>
> spice_assert(drawable && stream);
> spice_assert(!drawable->stream && !stream->current);
> @@ -279,7 +279,7 @@ static void attach_stream(DisplayChannel *display,
> Drawable *drawable, Stream *s
> stream->num_input_frames++;
> }
>
> - FOREACH_DCC(display, item, next, dcc) {
> + FOREACH_DCC(display, link, next, dcc) {
> StreamAgent *agent;
> QRegion clip_in_draw_dest;
>
> @@ -321,6 +321,7 @@ static void before_reattach_stream(DisplayChannel
> *display,
> int index;
> StreamAgent *agent;
> RingItem *ring_item, *next;
> + GList *link, *link_next;
>
> spice_return_if_fail(stream->current);
>
> @@ -356,7 +357,7 @@ static void before_reattach_stream(DisplayChannel
> *display,
> }
>
>
> - FOREACH_DCC(display, ring_item, next, dcc) {
> + FOREACH_DCC(display, link, link_next, dcc) {
> double drop_factor;
>
> agent = &dcc->stream_agents[index];
> @@ -401,7 +402,7 @@ static Stream
> *display_channel_stream_try_new(DisplayChannel *display)
> static void display_channel_create_stream(DisplayChannel *display, Drawable
> *drawable)
> {
> DisplayChannelClient *dcc;
> - RingItem *dcc_ring_item, *next;
> + GList *link, *next;
> Stream *stream;
> SpiceRect* src_rect;
>
> @@ -438,7 +439,7 @@ static void display_channel_create_stream(DisplayChannel
> *display, Drawable *dra
> stream->input_fps_start_time = drawable->creation_time;
> display->streams_size_total += stream->width * stream->height;
> display->stream_count++;
> - FOREACH_DCC(display, dcc_ring_item, next, dcc) {
> + FOREACH_DCC(display, link, next, dcc) {
> dcc_create_stream(dcc, stream);
> }
> spice_debug("stream %d %dx%d (%d, %d) (%d, %d) %u fps",
> @@ -840,10 +841,10 @@ clear_vis_region:
> static void detach_stream_gracefully(DisplayChannel *display, Stream
> *stream,
> Drawable *update_area_limit)
> {
> - RingItem *item, *next;
> + GList *link, *next;
> DisplayChannelClient *dcc;
>
> - FOREACH_DCC(display, item, next, dcc) {
> + FOREACH_DCC(display, link, next, dcc) {
> dcc_detach_stream_gracefully(dcc, stream, update_area_limit);
> }
> if (stream->current) {
> @@ -865,7 +866,7 @@ void stream_detach_behind(DisplayChannel *display,
> QRegion *region, Drawable *dr
> {
> Ring *ring = &display->streams;
> RingItem *item = ring_get_head(ring);
> - RingItem *dcc_ring_item, *next;
> + GList *link, *next;
> DisplayChannelClient *dcc;
> bool is_connected = red_channel_is_connected(RED_CHANNEL(display));
>
> @@ -874,7 +875,7 @@ void stream_detach_behind(DisplayChannel *display,
> QRegion *region, Drawable *dr
> int detach = 0;
> item = ring_next(ring, item);
>
> - FOREACH_DCC(display, dcc_ring_item, next, dcc) {
> + FOREACH_DCC(display, link, next, dcc) {
> StreamAgent *agent = &dcc->stream_agents[get_stream_id(display,
> stream)];
>
> if (region_intersects(&agent->vis_region, region)) {
I would prefer a new FOR macro instead of manual looping on the list.
Frediano
More information about the Spice-devel
mailing list