yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
lru_cache.h
Go to the documentation of this file.
1#ifndef YAZE_UTIL_LRU_CACHE_H_
2#define YAZE_UTIL_LRU_CACHE_H_
3
4#include <algorithm>
5#include <deque>
6#include <functional>
7#include <map>
8#include <utility>
9
10namespace yaze {
11namespace util {
12
13// A generic LRU (Least Recently Used) cache with configurable capacity
14// and an optional eviction predicate.
15//
16// Usage:
17// LruCache<int, std::unique_ptr<Widget>> cache(20);
18// cache.Insert(42, std::make_unique<Widget>());
19// Widget* w = cache.Get(42); // touches entry (moves to most recent)
20// cache.Touch(42); // explicit LRU refresh
21// cache.Erase(42); // manual removal
22//
23// Eviction:
24// When Insert would exceed capacity, the least recently used entry is
25// evicted. You can supply a predicate to skip entries that should not
26// be evicted (e.g., entries that are currently active/pinned):
27//
28// cache.SetEvictionPredicate([&](const Key& k) {
29// return !IsActive(k); // only evict inactive entries
30// });
31//
32template <typename Key, typename Value>
33class LruCache {
34 public:
35 using EvictionPredicate = std::function<bool(const Key&)>;
36
37 explicit LruCache(size_t capacity) : capacity_(capacity) {}
38
39 // Insert or replace an entry. Evicts the LRU entry if over capacity.
40 // Returns a pointer to the stored value.
41 Value* Insert(const Key& key, Value value) {
42 Erase(key); // Remove existing entry if present
43 entries_[key] = std::move(value);
44 lru_.push_back(key);
46 return &entries_[key];
47 }
48
49 // Get a pointer to the value, or nullptr if not found.
50 // Touches the entry (moves to most recent).
51 Value* Get(const Key& key) {
52 auto it = entries_.find(key);
53 if (it == entries_.end()) return nullptr;
54 Touch(key);
55 return &it->second;
56 }
57
58 // Get a pointer to the value without touching LRU order.
59 Value* Peek(const Key& key) {
60 auto it = entries_.find(key);
61 if (it == entries_.end()) return nullptr;
62 return &it->second;
63 }
64
65 // Check if a key exists in the cache.
66 bool Contains(const Key& key) const {
67 return entries_.find(key) != entries_.end();
68 }
69
70 // Move entry to most-recent position in LRU order.
71 void Touch(const Key& key) {
72 RemoveFromLru(key);
73 lru_.push_back(key);
74 }
75
76 // Remove an entry from the cache.
77 bool Erase(const Key& key) {
78 RemoveFromLru(key);
79 return entries_.erase(key) > 0;
80 }
81
82 // Transfer ownership of a key's value from old_key to new_key.
83 // If old_key doesn't exist, does nothing. If new_key already exists,
84 // it is replaced.
85 void Rename(const Key& old_key, const Key& new_key) {
86 auto it = entries_.find(old_key);
87 if (it == entries_.end()) return;
88 Value val = std::move(it->second);
89 entries_.erase(it);
90 RemoveFromLru(old_key);
91 Erase(new_key); // Remove new_key if it exists
92 entries_[new_key] = std::move(val);
93 lru_.push_back(new_key);
94 }
95
96 void Clear() {
97 entries_.clear();
98 lru_.clear();
99 }
100
101 size_t Size() const { return entries_.size(); }
102 size_t Capacity() const { return capacity_; }
103 bool Empty() const { return entries_.empty(); }
104
105 void SetCapacity(size_t capacity) {
106 capacity_ = capacity;
108 }
109
110 // Set a predicate that determines whether an entry CAN be evicted.
111 // If the predicate returns false, the entry is skipped during eviction.
113 eviction_predicate_ = std::move(pred);
114 }
115
116 // Iterate over all entries (key-value pairs).
117 template <typename Fn>
118 void ForEach(Fn&& fn) {
119 for (auto& [key, value] : entries_) {
120 fn(key, value);
121 }
122 }
123
124 template <typename Fn>
125 void ForEach(Fn&& fn) const {
126 for (const auto& [key, value] : entries_) {
127 fn(key, value);
128 }
129 }
130
131 // Access the underlying map (for cases needing direct iteration).
132 const std::map<Key, Value>& entries() const { return entries_; }
133 std::map<Key, Value>& mutable_entries() { return entries_; }
134
135 // Access the LRU order (oldest at front, newest at back).
136 const std::deque<Key>& lru_order() const { return lru_; }
137
138 private:
139 void RemoveFromLru(const Key& key) {
140 lru_.erase(std::remove(lru_.begin(), lru_.end(), key), lru_.end());
141 }
142
144 while (entries_.size() > capacity_) {
145 bool evicted = false;
146 for (auto it = lru_.begin(); it != lru_.end(); ++it) {
147 // Check eviction predicate if set
149 continue; // Skip protected entries
150 }
151 entries_.erase(*it);
152 lru_.erase(it);
153 evicted = true;
154 break;
155 }
156 if (!evicted) break; // All entries are protected; allow over-capacity
157 }
158 }
159
160 size_t capacity_;
161 std::map<Key, Value> entries_;
162 std::deque<Key> lru_;
164};
165
166} // namespace util
167} // namespace yaze
168
169#endif // YAZE_UTIL_LRU_CACHE_H_
std::map< Key, Value > entries_
Definition lru_cache.h:161
void SetEvictionPredicate(EvictionPredicate pred)
Definition lru_cache.h:112
EvictionPredicate eviction_predicate_
Definition lru_cache.h:163
std::map< Key, Value > & mutable_entries()
Definition lru_cache.h:133
void SetCapacity(size_t capacity)
Definition lru_cache.h:105
std::function< bool(const Key &)> EvictionPredicate
Definition lru_cache.h:35
void ForEach(Fn &&fn) const
Definition lru_cache.h:125
size_t Capacity() const
Definition lru_cache.h:102
Value * Peek(const Key &key)
Definition lru_cache.h:59
void ForEach(Fn &&fn)
Definition lru_cache.h:118
void RemoveFromLru(const Key &key)
Definition lru_cache.h:139
bool Contains(const Key &key) const
Definition lru_cache.h:66
Value * Insert(const Key &key, Value value)
Definition lru_cache.h:41
std::deque< Key > lru_
Definition lru_cache.h:162
void Touch(const Key &key)
Definition lru_cache.h:71
size_t Size() const
Definition lru_cache.h:101
const std::map< Key, Value > & entries() const
Definition lru_cache.h:132
LruCache(size_t capacity)
Definition lru_cache.h:37
bool Erase(const Key &key)
Definition lru_cache.h:77
void Rename(const Key &old_key, const Key &new_key)
Definition lru_cache.h:85
bool Empty() const
Definition lru_cache.h:103
const std::deque< Key > & lru_order() const
Definition lru_cache.h:136
Value * Get(const Key &key)
Definition lru_cache.h:51