libaaruformat 1.0
Aaru Data Preservation Suite - Format Library
Loading...
Searching...
No Matches
lru.c
Go to the documentation of this file.
1#include <stddef.h>
2#include <stdint.h>
3#include <stdlib.h>
4#include <uthash.h>
5
6#include <aaruformat.h>
7
8// LRU cache using uthash with native integer keys.
9// Based on uthash LRU example by Jehiah Czebotar 2011 (public domain).
10// Rewritten to use HASH_FIND/HASH_ADD with uint64_t keys directly,
11// eliminating all string conversion, malloc, and snprintf overhead
12// from the hot path.
13
20static void drop_entry(struct CacheHeader *cache, struct CacheEntry *entry)
21{
22 HASH_DELETE(hh, cache->cache, entry);
23
24 cache->cur_bytes -= entry->size;
25
26 if(cache->free_func && entry->value) cache->free_func(entry->value);
27
28 free(entry);
29}
30
41void *find_in_cache_uint64(struct CacheHeader *cache, const uint64_t key)
42{
43 struct CacheEntry *entry = NULL;
44 HASH_FIND(hh, cache->cache, &key, sizeof(uint64_t), entry);
45 if(entry)
46 {
47 // Remove and re-add to move to front of insertion-order list (LRU refresh).
48 HASH_DELETE(hh, cache->cache, entry);
49 HASH_ADD(hh, cache->cache, key, sizeof(uint64_t), entry);
50 return entry->value;
51 }
52 return NULL;
53}
54
68void add_to_cache_uint64(struct CacheHeader *cache, const uint64_t key, void *value, const size_t size)
69{
70 struct CacheEntry *entry = NULL;
71
72 // Replace an existing entry for this key. A blind HASH_ADD would leave the old entry in the
73 // table unreachable by HASH_FIND, and its value alive until the whole cache is freed.
74 HASH_FIND(hh, cache->cache, &key, sizeof(uint64_t), entry);
75
76 if(entry)
77 {
78 cache->cur_bytes -= entry->size;
79
80 if(cache->free_func && entry->value && entry->value != value) cache->free_func(entry->value);
81
82 HASH_DELETE(hh, cache->cache, entry);
83 }
84 else
85 {
86 entry = malloc(sizeof(struct CacheEntry));
87 if(!entry) return;
88 }
89
90 entry->key = key;
91 entry->value = value;
92 entry->size = size;
93 HASH_ADD(hh, cache->cache, key, sizeof(uint64_t), entry);
94 cache->cur_bytes += size;
95
96 if(cache->max_bytes == 0) return;
97
98 // Evict least recently used entries until back under budget. Never evict the entry just
99 // inserted: the caller still uses that pointer after this returns.
100 while(cache->cur_bytes > cache->max_bytes && HASH_COUNT(cache->cache) > 1)
101 {
102 struct CacheEntry *oldest = cache->cache;
103
104 if(oldest == NULL || oldest == entry) break;
105
106 drop_entry(cache, oldest);
107 }
108}
109
118void free_cache(struct CacheHeader *cache)
119{
120 struct CacheEntry *entry, *tmp;
121
122 if(!cache || !cache->cache) return;
123
124 HASH_ITER(hh, cache->cache, entry, tmp) { drop_entry(cache, entry); }
125
126 cache->cache = NULL;
127 cache->cur_bytes = 0;
128}
static void drop_entry(struct CacheHeader *cache, struct CacheEntry *entry)
Frees a cache entry's value and unlinks it from the cache.
Definition lru.c:20
void add_to_cache_uint64(struct CacheHeader *cache, uint64_t key, void *value, size_t size)
Adds a value to the cache with a uint64_t key, evicting LRU entries if over budget.
Definition lru.c:68
void * find_in_cache_uint64(struct CacheHeader *cache, uint64_t key)
Finds a value in the cache by uint64_t key.
Definition lru.c:41
void free_cache(struct CacheHeader *cache)
Frees all entries in the cache and clears it.
Definition lru.c:118
Single hash entry in the in-memory cache.
Definition lru.h:25
void * value
Opaque value pointer associated with key.
Definition lru.h:27
size_t size
Size in bytes of the memory pointed to by value.
Definition lru.h:28
uint64_t key
64-bit integer key (unique within the cache).
Definition lru.h:26
UT_hash_handle hh
uthash handle (must remain per uthash docs).
Definition lru.h:29
Cache top-level descriptor encapsulating the hash table root and capacity limit.
Definition lru.h:51
struct CacheEntry * cache
Hash root (uthash). NULL when empty.
Definition lru.h:54
void(*) free_func(void *)
Optional callback to free cached values. NULL if not needed.
Definition lru.h:55
uint64_t cur_bytes
Bytes currently held by the cached values.
Definition lru.h:53
uint64_t max_bytes
Memory budget in bytes for the cached values. 0 means unlimited.
Definition lru.h:52