summaryrefslogtreecommitdiffstats
path: root/server/pixmap-cache.c
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@gmail.com>2013-09-03 00:01:04 +0200
committerFrediano Ziglio <fziglio@redhat.com>2015-10-19 13:08:21 +0100
commitb15527e06352acc38fff7601cb22301a85afe410 (patch)
tree6f0f24fb62b9db8ae07f5d19bd192a0774fced4c /server/pixmap-cache.c
parentc749853d08c659c272207ea69762edeae219d631 (diff)
downloadspice-b15527e06352acc38fff7601cb22301a85afe410.tar.gz
spice-b15527e06352acc38fff7601cb22301a85afe410.tar.xz
spice-b15527e06352acc38fff7601cb22301a85afe410.zip
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 <fziglio@redhat.com>
Diffstat (limited to 'server/pixmap-cache.c')
-rw-r--r--server/pixmap-cache.c142
1 files changed, 142 insertions, 0 deletions
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 <http://www.gnu.org/licenses/>.
+*/
+#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);
+}