This patch is intended to be merged into "RedChannelClient: store pipe items in a GList".
GQueue improve GList for pipe usage as tail inserting/removal/access are O(1) instead of O(n). Also getting the number of items is O(1) instead of O(n). Signed-off-by: Frediano Ziglio <fzig...@redhat.com> --- server/dcc-send.c | 12 ++++---- server/dcc.c | 2 +- server/display-channel.c | 5 +--- server/red-channel-client-private.h | 2 +- server/red-channel-client.c | 58 +++++++++++++++++-------------------- server/red-channel-client.h | 2 +- 6 files changed, 36 insertions(+), 45 deletions(-) diff --git a/server/dcc-send.c b/server/dcc-send.c index 187eaca..8bcba77 100644 --- a/server/dcc-send.c +++ b/server/dcc-send.c @@ -189,9 +189,8 @@ static int is_brush_lossy(RedChannelClient *rcc, SpiceBrush *brush, static RedPipeItem *dcc_get_tail(DisplayChannelClient *dcc) { - GList *pipe = red_channel_client_get_pipe(RED_CHANNEL_CLIENT(dcc)); - GList *last = g_list_last(pipe); - return last->data; + GQueue *pipe = red_channel_client_get_pipe(RED_CHANNEL_CLIENT(dcc)); + return g_queue_peek_tail(pipe); } static void red_display_add_image_to_pixmap_cache(RedChannelClient *rcc, @@ -623,7 +622,7 @@ static int pipe_rendered_drawables_intersect_with_areas(DisplayChannelClient *dc spice_assert(num_surfaces); - for (l = red_channel_client_get_pipe(RED_CHANNEL_CLIENT(dcc)); l != NULL; l = l->next) { + for (l = red_channel_client_get_pipe(RED_CHANNEL_CLIENT(dcc))->head; l != NULL; l = l->next) { Drawable *drawable; RedPipeItem *pipe_item = l->data; @@ -704,7 +703,8 @@ static void red_pipe_replace_rendered_drawables_with_images(DisplayChannelClient int resent_surface_ids[MAX_PIPE_SIZE]; SpiceRect resent_areas[MAX_PIPE_SIZE]; // not pointers since drawables may be released int num_resent; - GList *l, *pipe; + GList *l; + GQueue *pipe; resent_surface_ids[0] = first_surface_id; resent_areas[0] = *first_area; @@ -713,7 +713,7 @@ static void red_pipe_replace_rendered_drawables_with_images(DisplayChannelClient pipe = red_channel_client_get_pipe(RED_CHANNEL_CLIENT(dcc)); // going from the oldest to the newest - for (l = g_list_last(pipe); l != NULL; l = l->prev) { + for (l = pipe->tail; l != NULL; l = l->prev) { RedPipeItem *pipe_item = l->data; Drawable *drawable; RedDrawablePipeItem *dpi; diff --git a/server/dcc.c b/server/dcc.c index b12d034..0d672df 100644 --- a/server/dcc.c +++ b/server/dcc.c @@ -78,7 +78,7 @@ int dcc_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int surface no other drawable depends on them */ rcc = RED_CHANNEL_CLIENT(dcc); - l = rcc->priv->pipe; + l = rcc->priv->pipe.head; while (l != NULL) { GList *cur = l; Drawable *drawable; diff --git a/server/display-channel.c b/server/display-channel.c index bd2907f..de25161 100644 --- a/server/display-channel.c +++ b/server/display-channel.c @@ -331,10 +331,7 @@ static void drawable_remove_from_pipes(Drawable *drawable) dpi = SPICE_UPCAST(RedDrawablePipeItem, item); rcc = RED_CHANNEL_CLIENT(dpi->dcc); - if (red_channel_client_pipe_item_is_linked(rcc, &dpi->dpi_pipe_item)) { - red_channel_client_pipe_remove_and_release(rcc, - &dpi->dpi_pipe_item); - } + red_channel_client_pipe_remove_and_release(rcc, &dpi->dpi_pipe_item); } } diff --git a/server/red-channel-client-private.h b/server/red-channel-client-private.h index b13f905..8eaa570 100644 --- a/server/red-channel-client-private.h +++ b/server/red-channel-client-private.h @@ -59,7 +59,7 @@ struct RedChannelClientPrivate int during_send; int id; // debugging purposes - GList *pipe; + GQueue pipe; RedChannelCapabilities remote_caps; int is_mini_header; diff --git a/server/red-channel-client.c b/server/red-channel-client.c index 9f678d7..89ab679 100644 --- a/server/red-channel-client.c +++ b/server/red-channel-client.c @@ -344,7 +344,7 @@ void red_channel_client_on_out_msg_done(void *opaque) } else { if (rcc->priv->latency_monitor.timer && !rcc->priv->send_data.blocked - && rcc->priv->pipe == NULL) { + && g_queue_is_empty(&rcc->priv->pipe)) { /* It is possible that the socket will become idle, so we may be able to test latency */ red_channel_client_restart_ping_timer(rcc); } @@ -352,9 +352,9 @@ void red_channel_client_on_out_msg_done(void *opaque) } -static void red_channel_client_pipe_remove(RedChannelClient *rcc, RedPipeItem *item) +static gboolean red_channel_client_pipe_remove(RedChannelClient *rcc, RedPipeItem *item) { - rcc->priv->pipe = g_list_remove(rcc->priv->pipe, item); + return g_queue_remove(&rcc->priv->pipe, item); } static void red_channel_client_set_remote_caps(RedChannelClient* rcc, @@ -680,7 +680,7 @@ RedChannelClient *red_channel_client_create(int size, RedChannel *channel, RedCl goto error; } - rcc->priv->pipe = NULL; + g_queue_init(&rcc->priv->pipe); stream->watch = channel->core->watch_add(channel->core, stream->socket, @@ -741,7 +741,7 @@ RedChannelClient *red_channel_client_create_dummy(int size, rcc->incoming.header.data = rcc->incoming.header_buf; rcc->incoming.serial = 1; - rcc->priv->pipe = NULL; + g_queue_init(&rcc->priv->pipe); rcc->priv->dummy = TRUE; rcc->priv->dummy_connected = TRUE; @@ -1037,17 +1037,11 @@ void red_channel_client_send(RedChannelClient *rcc) static inline RedPipeItem *red_channel_client_pipe_item_get(RedChannelClient *rcc) { - GList *l; - RedPipeItem *item; - if (!rcc || rcc->priv->send_data.blocked - || red_channel_client_waiting_for_ack(rcc) - || !(l = g_list_last(rcc->priv->pipe))) { + || red_channel_client_waiting_for_ack(rcc)) { return NULL; } - item = l->data; - rcc->priv->pipe = g_list_delete_link(rcc->priv->pipe, l); - return item; + return g_queue_pop_tail(&rcc->priv->pipe); } void red_channel_client_push(RedChannelClient *rcc) @@ -1072,7 +1066,7 @@ void red_channel_client_push(RedChannelClient *rcc) while ((pipe_item = red_channel_client_pipe_item_get(rcc))) { red_channel_client_send_item(rcc, pipe_item); } - if (red_channel_client_no_item_being_sent(rcc) && rcc->priv->pipe == NULL + if (red_channel_client_no_item_being_sent(rcc) && g_queue_is_empty(&rcc->priv->pipe) && rcc->priv->stream->watch) { rcc->priv->channel->core->watch_update_mask(rcc->priv->stream->watch, SPICE_WATCH_EVENT_READ); @@ -1294,7 +1288,7 @@ static inline gboolean prepare_pipe_add(RedChannelClient *rcc, RedPipeItem *item red_pipe_item_unref(item); return FALSE; } - if (rcc->priv->pipe == NULL && rcc->priv->stream->watch) { + if (g_queue_is_empty(&rcc->priv->pipe) && rcc->priv->stream->watch) { rcc->priv->channel->core->watch_update_mask(rcc->priv->stream->watch, SPICE_WATCH_EVENT_READ | SPICE_WATCH_EVENT_WRITE); @@ -1308,7 +1302,7 @@ void red_channel_client_pipe_add(RedChannelClient *rcc, RedPipeItem *item) if (!prepare_pipe_add(rcc, item)) { return; } - rcc->priv->pipe = g_list_prepend(rcc->priv->pipe, item); + g_queue_push_head(&rcc->priv->pipe, item); } void red_channel_client_pipe_add_push(RedChannelClient *rcc, RedPipeItem *item) @@ -1327,16 +1321,16 @@ void red_channel_client_pipe_add_after(RedChannelClient *rcc, if (!prepare_pipe_add(rcc, item)) { return; } - prev = g_list_find(rcc->priv->pipe, pos); + prev = g_queue_find(&rcc->priv->pipe, pos); g_return_if_fail(prev != NULL); - rcc->priv->pipe = g_list_insert_before(rcc->priv->pipe, prev->next, item); + g_queue_insert_after(&rcc->priv->pipe, prev, item); } int red_channel_client_pipe_item_is_linked(RedChannelClient *rcc, RedPipeItem *item) { - return g_list_find(rcc->priv->pipe, item) != NULL; + return g_queue_find(&rcc->priv->pipe, item) != NULL; } void red_channel_client_pipe_add_tail(RedChannelClient *rcc, @@ -1345,7 +1339,7 @@ void red_channel_client_pipe_add_tail(RedChannelClient *rcc, if (!prepare_pipe_add(rcc, item)) { return; } - rcc->priv->pipe = g_list_append(rcc->priv->pipe, item); + g_queue_push_tail(&rcc->priv->pipe, item); } void red_channel_client_pipe_add_tail_and_push(RedChannelClient *rcc, RedPipeItem *item) @@ -1353,7 +1347,7 @@ void red_channel_client_pipe_add_tail_and_push(RedChannelClient *rcc, RedPipeIte if (!prepare_pipe_add(rcc, item)) { return; } - rcc->priv->pipe = g_list_append(rcc->priv->pipe, item); + g_queue_push_tail(&rcc->priv->pipe, item); red_channel_client_push(rcc); } @@ -1379,17 +1373,17 @@ void red_channel_client_pipe_add_empty_msg(RedChannelClient *rcc, int msg_type) gboolean red_channel_client_pipe_is_empty(RedChannelClient *rcc) { g_return_val_if_fail(rcc != NULL, TRUE); - return (rcc->priv->pipe == NULL); + return g_queue_is_empty(&rcc->priv->pipe); } uint32_t red_channel_client_get_pipe_size(RedChannelClient *rcc) { - return g_list_length(rcc->priv->pipe); + return g_queue_get_length(&rcc->priv->pipe); } -GList* red_channel_client_get_pipe(RedChannelClient *rcc) +GQueue* red_channel_client_get_pipe(RedChannelClient *rcc) { - return rcc->priv->pipe; + return &rcc->priv->pipe; } gboolean red_channel_client_is_mini_header(RedChannelClient *rcc) @@ -1419,14 +1413,13 @@ static void red_channel_client_clear_sent_item(RedChannelClient *rcc) // are we reading from an fd here? arghh static void red_channel_client_pipe_clear(RedChannelClient *rcc) { - GList *l; + RedPipeItem *item; if (rcc) { red_channel_client_clear_sent_item(rcc); } - while ((l = rcc->priv->pipe)) { - red_pipe_item_unref(l->data); - rcc->priv->pipe = g_list_delete_link(rcc->priv->pipe, l); + while ((item = g_queue_pop_head(&rcc->priv->pipe)) != NULL) { + red_pipe_item_unref(item); } } @@ -1611,7 +1604,7 @@ int red_channel_client_wait_outgoing_item(RedChannelClient *rcc, void red_channel_client_disconnect_if_pending_send(RedChannelClient *rcc) { - if (red_channel_client_is_blocked(rcc) || rcc->priv->pipe != NULL) { + if (red_channel_client_is_blocked(rcc) || !g_queue_is_empty(&rcc->priv->pipe)) { red_channel_client_disconnect(rcc); } else { spice_assert(red_channel_client_no_item_being_sent(rcc)); @@ -1626,8 +1619,9 @@ gboolean red_channel_client_no_item_being_sent(RedChannelClient *rcc) void red_channel_client_pipe_remove_and_release(RedChannelClient *rcc, RedPipeItem *item) { - red_channel_client_pipe_remove(rcc, item); - red_pipe_item_unref(item); + if (red_channel_client_pipe_remove(rcc, item)) { + red_pipe_item_unref(item); + } } /* client mutex should be locked before this call */ diff --git a/server/red-channel-client.h b/server/red-channel-client.h index 249e7fe..e77936d 100644 --- a/server/red-channel-client.h +++ b/server/red-channel-client.h @@ -114,7 +114,7 @@ void red_channel_client_pipe_add_type(RedChannelClient *rcc, int pipe_item_type) void red_channel_client_pipe_add_empty_msg(RedChannelClient *rcc, int msg_type); gboolean red_channel_client_pipe_is_empty(RedChannelClient *rcc); uint32_t red_channel_client_get_pipe_size(RedChannelClient *rcc); -GList* red_channel_client_get_pipe(RedChannelClient *rcc); +GQueue* red_channel_client_get_pipe(RedChannelClient *rcc); gboolean red_channel_client_is_mini_header(RedChannelClient *rcc); void red_channel_client_ack_zero_messages_window(RedChannelClient *rcc); -- 2.7.4 _______________________________________________ Spice-devel mailing list Spice-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/spice-devel