From b15527e06352acc38fff7601cb22301a85afe410 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Tue, 3 Sep 2013 00:01:04 +0200 Subject: server: move some pixmap cache code in own file Remove that hideous template header that should really be regular code since it's specialized and instanciated only for pixmap. Acked-by: Frediano Ziglio --- server/pixmap-cache.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 server/pixmap-cache.c (limited to 'server/pixmap-cache.c') diff --git a/server/pixmap-cache.c b/server/pixmap-cache.c new file mode 100644 index 00000000..61d225e8 --- /dev/null +++ b/server/pixmap-cache.c @@ -0,0 +1,142 @@ +/* + Copyright (C) 2009-2015 Red Hat, Inc. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see . +*/ +#include "pixmap-cache.h" + +int pixmap_cache_unlocked_set_lossy(PixmapCache *cache, uint64_t id, int lossy) +{ + NewCacheItem *item; + + item = cache->hash_table[BITS_CACHE_HASH_KEY(id)]; + + while (item) { + if (item->id == id) { + item->lossy = lossy; + break; + } + item = item->next; + } + return !!item; +} + +void pixmap_cache_clear(PixmapCache *cache) +{ + NewCacheItem *item; + + if (cache->freezed) { + cache->lru.next = cache->freezed_head; + cache->lru.prev = cache->freezed_tail; + cache->freezed = FALSE; + } + + while ((item = (NewCacheItem *)ring_get_head(&cache->lru))) { + ring_remove(&item->lru_link); + free(item); + } + memset(cache->hash_table, 0, sizeof(*cache->hash_table) * BITS_CACHE_HASH_SIZE); + + cache->available = cache->size; + cache->items = 0; +} + +int pixmap_cache_freeze(PixmapCache *cache) +{ + pthread_mutex_lock(&cache->lock); + + if (cache->freezed) { + pthread_mutex_unlock(&cache->lock); + return FALSE; + } + + cache->freezed_head = cache->lru.next; + cache->freezed_tail = cache->lru.prev; + ring_init(&cache->lru); + memset(cache->hash_table, 0, sizeof(*cache->hash_table) * BITS_CACHE_HASH_SIZE); + cache->available = -1; + cache->freezed = TRUE; + + pthread_mutex_unlock(&cache->lock); + return TRUE; +} + +static void pixmap_cache_destroy(PixmapCache *cache) +{ + spice_assert(cache); + + pthread_mutex_lock(&cache->lock); + pixmap_cache_clear(cache); + pthread_mutex_unlock(&cache->lock); +} + + +static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER; +static Ring pixmap_cache_list = {&pixmap_cache_list, &pixmap_cache_list}; + +static PixmapCache *pixmap_cache_new(RedClient *client, uint8_t id, int64_t size) +{ + PixmapCache *cache = spice_new0(PixmapCache, 1); + + ring_item_init(&cache->base); + pthread_mutex_init(&cache->lock, NULL); + cache->id = id; + cache->refs = 1; + ring_init(&cache->lru); + cache->available = size; + cache->size = size; + cache->client = client; + + return cache; +} + +PixmapCache *pixmap_cache_get(RedClient *client, uint8_t id, int64_t size) +{ + PixmapCache *ret = NULL; + RingItem *now; + pthread_mutex_lock(&cache_lock); + + now = &pixmap_cache_list; + while ((now = ring_next(&pixmap_cache_list, now))) { + PixmapCache *cache = (PixmapCache *)now; + if ((cache->client == client) && (cache->id == id)) { + ret = cache; + ret->refs++; + break; + } + } + if (!ret) { + ret = pixmap_cache_new(client, id, size); + ring_add(&pixmap_cache_list, &ret->base); + } + pthread_mutex_unlock(&cache_lock); + return ret; +} + + +void pixmap_cache_unref(PixmapCache *cache) +{ + if (!cache) + return; + + pthread_mutex_lock(&cache_lock); + if (--cache->refs) { + pthread_mutex_unlock(&cache_lock); + return; + } + ring_remove(&cache->base); + pthread_mutex_unlock(&cache_lock); + pixmap_cache_destroy(cache); + free(cache); +} -- cgit