[Spice-devel] [PATCH 1/2] Change GList in GQueue

Frediano Ziglio fziglio at redhat.com
Mon Sep 12 15:32:02 UTC 2016


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 <fziglio at 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



More information about the Spice-devel mailing list