2019-05-03 11:20:47 -04:00
|
|
|
#pragma once
|
|
|
|
|
2024-02-15 16:08:48 -05:00
|
|
|
#include <uthash.h>
|
|
|
|
#include "utils.h"
|
|
|
|
|
|
|
|
#define cache_entry(ptr, type, member) container_of(ptr, type, member)
|
|
|
|
|
2019-05-03 11:20:47 -04:00
|
|
|
struct cache;
|
2024-02-15 16:08:48 -05:00
|
|
|
struct cache_handle;
|
|
|
|
|
|
|
|
/// User-provided function to fetch a value for the cache, when it's not present.
|
|
|
|
/// Should return 0 if the value is fetched successfully, and a negative number if the
|
|
|
|
/// value cannot be fetched. Getter doesn't need to initialize fields of `struct
|
|
|
|
/// cache_handle`.
|
2024-02-17 19:40:07 -05:00
|
|
|
typedef int (*cache_getter_t)(struct cache *, const char *key, size_t keylen,
|
2024-02-15 19:31:53 -05:00
|
|
|
struct cache_handle **value, void *user_data);
|
2024-02-15 16:08:48 -05:00
|
|
|
typedef void (*cache_free_t)(struct cache *, struct cache_handle *value);
|
2019-05-03 11:20:47 -04:00
|
|
|
|
2024-02-15 16:08:48 -05:00
|
|
|
struct cache {
|
|
|
|
struct cache_handle *entries;
|
|
|
|
};
|
2020-12-26 02:25:34 -05:00
|
|
|
|
2024-02-15 19:31:53 -05:00
|
|
|
static const struct cache CACHE_INIT = {NULL};
|
|
|
|
|
2024-02-15 16:08:48 -05:00
|
|
|
struct cache_handle {
|
|
|
|
char *key;
|
|
|
|
UT_hash_handle hh;
|
|
|
|
};
|
|
|
|
|
2024-02-15 15:05:09 -05:00
|
|
|
/// Get a value from the cache. If the value doesn't present in the cache yet, the
|
2020-12-26 02:25:34 -05:00
|
|
|
/// getter will be called, and the returned value will be stored into the cache.
|
2024-02-15 16:08:48 -05:00
|
|
|
/// Returns 0 if the value is already present in the cache, 1 if the value is fetched
|
|
|
|
/// successfully, and a negative number if the value cannot be fetched.
|
2024-02-17 19:40:07 -05:00
|
|
|
int cache_get_or_fetch(struct cache *, const char *key, size_t keylen,
|
|
|
|
struct cache_handle **value, void *user_data, cache_getter_t getter);
|
2024-02-15 15:05:09 -05:00
|
|
|
|
|
|
|
/// Get a value from the cache. If the value doesn't present in the cache, NULL will be
|
|
|
|
/// returned.
|
2024-02-17 19:40:07 -05:00
|
|
|
struct cache_handle *cache_get(struct cache *, const char *key, size_t keylen);
|
2020-12-26 02:25:34 -05:00
|
|
|
|
2024-02-15 16:08:48 -05:00
|
|
|
/// Invalidate all values in the cache. After this call, `struct cache` holds no allocated
|
|
|
|
/// memory, and can be discarded.
|
|
|
|
void cache_invalidate_all(struct cache *, cache_free_t free_fn);
|