diff --git a/server/cache-item.h b/server/cache-item.h index f0002a86..610d1b8f 100644 --- a/server/cache-item.h +++ b/server/cache-item.h @@ -23,17 +23,16 @@ #include "red-pipe-item.h" -typedef struct RedCacheItem RedCacheItem; +/* pipe item used to release a specific cached item on the client */ +struct RedCachePipeItem { + RedPipeItem base; + uint64_t id; +}; struct RedCacheItem { - union { - RedPipeItem pipe_data; - struct { - RingItem lru_link; - RedCacheItem *next; - size_t size; - } cache_data; - } u; + RingItem lru_link; + RedCacheItem *next; + size_t size; uint64_t id; }; diff --git a/server/cache-item.tmpl.cpp b/server/cache-item.tmpl.cpp index 8aaadafd..89e75144 100644 --- a/server/cache-item.tmpl.cpp +++ b/server/cache-item.tmpl.cpp @@ -46,11 +46,11 @@ static RedCacheItem *FUNC_NAME(find)(CHANNELCLIENT *channel_client, uint64_t id) while (item) { if (item->id == id) { - ring_remove(&item->u.cache_data.lru_link); - ring_add(&channel_client->priv->VAR_NAME(lru), &item->u.cache_data.lru_link); + ring_remove(&item->lru_link); + ring_add(&channel_client->priv->VAR_NAME(lru), &item->lru_link); break; } - item = item->u.cache_data.next; + item = item->next; } return item; } @@ -64,16 +64,21 @@ static void FUNC_NAME(remove)(CHANNELCLIENT *channel_client, RedCacheItem *item) for (;;) { spice_assert(*now); if (*now == item) { - *now = item->u.cache_data.next; + *now = item->next; break; } - now = &(*now)->u.cache_data.next; + now = &(*now)->next; } - ring_remove(&item->u.cache_data.lru_link); - channel_client->priv->VAR_NAME(available) += item->u.cache_data.size; + ring_remove(&item->lru_link); + channel_client->priv->VAR_NAME(available) += item->size; - red_pipe_item_init(&item->u.pipe_data, RED_PIPE_ITEM_TYPE_INVAL_ONE); - channel_client->pipe_add_tail(&item->u.pipe_data); // for now + // see "Optimization" comment on add function below + auto id = item->id; + RedCachePipeItem *pipe_item = reinterpret_cast(item); + + red_pipe_item_init(&pipe_item->base, RED_PIPE_ITEM_TYPE_INVAL_ONE); + pipe_item->id = id; + channel_client->pipe_add_tail(&pipe_item->base); // for now } static int FUNC_NAME(add)(CHANNELCLIENT *channel_client, uint64_t id, size_t size) @@ -81,13 +86,20 @@ static int FUNC_NAME(add)(CHANNELCLIENT *channel_client, uint64_t id, size_t siz RedCacheItem *item; int key; - item = g_new(RedCacheItem, 1); + /* Optimization: allocate memory in order to be able to store + * both cache item and pipe item to be able to reuse it when + * we need to remove cache telling client */ + union RedCachePoolItem { + RedCacheItem cache_item; + RedCachePipeItem pipe_item; + }; + item = (RedCacheItem *) g_new(RedCachePoolItem, 1); channel_client->priv->VAR_NAME(available) -= size; - SPICE_VERIFY(SPICE_OFFSETOF(RedCacheItem, u.cache_data.lru_link) == 0); + SPICE_VERIFY(SPICE_OFFSETOF(RedCacheItem, lru_link) == 0); while (channel_client->priv->VAR_NAME(available) < 0) { RedCacheItem *tail = SPICE_CONTAINEROF(ring_get_tail(&channel_client->priv->VAR_NAME(lru)), - RedCacheItem, u.cache_data.lru_link); + RedCacheItem, lru_link); if (!tail) { channel_client->priv->VAR_NAME(available) += size; g_free(item); @@ -95,12 +107,12 @@ static int FUNC_NAME(add)(CHANNELCLIENT *channel_client, uint64_t id, size_t siz } FUNC_NAME(remove)(channel_client, tail); } - item->u.cache_data.next = channel_client->priv->CACHE_NAME[(key = CACHE_HASH_KEY(id))]; + item->next = channel_client->priv->CACHE_NAME[(key = CACHE_HASH_KEY(id))]; channel_client->priv->CACHE_NAME[key] = item; - ring_item_init(&item->u.cache_data.lru_link); - ring_add(&channel_client->priv->VAR_NAME(lru), &item->u.cache_data.lru_link); + ring_item_init(&item->lru_link); + ring_add(&channel_client->priv->VAR_NAME(lru), &item->lru_link); item->id = id; - item->u.cache_data.size = size; + item->size = size; return TRUE; } @@ -111,7 +123,7 @@ static void FUNC_NAME(reset)(CHANNELCLIENT *channel_client, long size) for (i = 0; i < CACHE_HASH_SIZE; i++) { while (channel_client->priv->CACHE_NAME[i]) { RedCacheItem *item = channel_client->priv->CACHE_NAME[i]; - channel_client->priv->CACHE_NAME[i] = item->u.cache_data.next; + channel_client->priv->CACHE_NAME[i] = item->next; g_free(item); } } diff --git a/server/cursor-channel.cpp b/server/cursor-channel.cpp index c8d4a227..cae2a72d 100644 --- a/server/cursor-channel.cpp +++ b/server/cursor-channel.cpp @@ -166,12 +166,12 @@ static void red_marshall_cursor(CursorChannelClient *ccc, static inline void red_marshall_inval(RedChannelClient *rcc, SpiceMarshaller *base_marshaller, - RedCacheItem *cach_item) + RedCachePipeItem *cache_item) { SpiceMsgDisplayInvalOne inval_one; rcc->init_send_data(SPICE_MSG_CURSOR_INVAL_ONE); - inval_one.id = cach_item->id; + inval_one.id = cache_item->id; spice_marshall_msg_cursor_inval_one(base_marshaller, &inval_one); } @@ -186,7 +186,7 @@ void CursorChannelClient::send_item(RedPipeItem *pipe_item) red_marshall_cursor(ccc, m, SPICE_UPCAST(RedCursorPipeItem, pipe_item)); break; case RED_PIPE_ITEM_TYPE_INVAL_ONE: - red_marshall_inval(this, m, SPICE_CONTAINEROF(pipe_item, RedCacheItem, u.pipe_data)); + red_marshall_inval(this, m, SPICE_UPCAST(RedCachePipeItem, pipe_item)); break; case RED_PIPE_ITEM_TYPE_CURSOR_INIT: reset_cursor_cache(); diff --git a/server/dcc-send.cpp b/server/dcc-send.cpp index 333682e1..b6b4d5b4 100644 --- a/server/dcc-send.cpp +++ b/server/dcc-send.cpp @@ -1740,7 +1740,7 @@ static bool red_marshall_stream_data(DisplayChannelClient *dcc, static inline void marshall_inval_palette(RedChannelClient *rcc, SpiceMarshaller *base_marshaller, - RedCacheItem *cache_item) + RedCachePipeItem *cache_item) { SpiceMsgDisplayInvalOne inval_one; @@ -2345,7 +2345,7 @@ void DisplayChannelClient::send_item(RedPipeItem *pipe_item) break; } case RED_PIPE_ITEM_TYPE_INVAL_ONE: - marshall_inval_palette(this, m, SPICE_CONTAINEROF(pipe_item, RedCacheItem, u.pipe_data)); + marshall_inval_palette(this, m, SPICE_UPCAST(RedCachePipeItem, pipe_item)); break; case RED_PIPE_ITEM_TYPE_STREAM_CREATE: { StreamCreateDestroyItem *item = SPICE_UPCAST(StreamCreateDestroyItem, pipe_item);