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)) 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; 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; 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; 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)) { -- 2.4.11 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel