From c08fd08ea4dab26295353aa2a2edeb88479dc05f Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Fri, 3 May 2019 16:20:47 +0100 Subject: [PATCH] Add a general key-value caching framework Signed-off-by: Yuxuan Shui --- src/cache.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ src/cache.h | 14 +++++++++++ src/meson.build | 2 +- 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 src/cache.c create mode 100644 src/cache.h diff --git a/src/cache.c b/src/cache.c new file mode 100644 index 0000000..69ba64d --- /dev/null +++ b/src/cache.c @@ -0,0 +1,62 @@ +#include + +#include "utils.h" +#include "cache.h" + +struct cache_entry { + char *key; + void *value; + UT_hash_handle hh; +}; + +struct cache { + cache_getter_t getter; + cache_free_t free; + void *user_data; + struct cache_entry *entries; +}; + +void *cache_get(struct cache *c, const char *key) { + struct cache_entry *e; + HASH_FIND_STR(c->entries, key, e); + if (e) { + return e->value; + } + + e = ccalloc(1, struct cache_entry); + e->key = strdup(key); + e->value = c->getter(c->user_data, key); + HASH_ADD_STR(c->entries, key, e); + return e->value; +} + +static inline void _cache_invalidate(struct cache *c, struct cache_entry *e) { + if (c->free) { + c->free(c->user_data, e->value); + } + HASH_DEL(c->entries, e); + free(e); +} + +void cache_invalidate(struct cache *c, const char *key) { + struct cache_entry *e; + HASH_FIND_STR(c->entries, key, e); + + if (e) { + _cache_invalidate(c, e); + } +} + +void cache_invalidate_all(struct cache *c) { + struct cache_entry *e, *tmpe; + HASH_ITER(hh, c->entries, e, tmpe) { + _cache_invalidate(c, e); + } +} + +void *cache_free(struct cache *c) { + void *ret = c->user_data; + cache_invalidate_all(c); + free(c); + return ret; +} diff --git a/src/cache.h b/src/cache.h new file mode 100644 index 0000000..440f92f --- /dev/null +++ b/src/cache.h @@ -0,0 +1,14 @@ +#pragma once + +struct cache; + +typedef void *(*cache_getter_t)(void *user_data, const char *key); +typedef void (*cache_free_t)(void *user_data, void *data); +struct cache *new_cache(void *user_data, cache_getter_t getter, cache_free_t f); + +void *cache_get(struct cache *, const char *key); +void cache_invalidate(struct cache *, const char *key); +void cache_invalidate_all(struct cache *); + +/// Returns the user data passed to `new_cache` +void *cache_free(struct cache *); diff --git a/src/meson.build b/src/meson.build index 88e9354..e337434 100644 --- a/src/meson.build +++ b/src/meson.build @@ -10,7 +10,7 @@ base_deps = [ srcs = [ files('compton.c', 'win.c', 'c2.c', 'x.c', 'config.c', 'vsync.c', 'utils.c', 'diagnostic.c', 'string_utils.c', 'render.c', 'kernel.c', 'log.c', - 'options.c', 'event.c') ] + 'options.c', 'event.c', 'cache.c') ] compton_inc = include_directories('.') cflags = []