quic/qbox
Loading...
Searching...
No Matches
addrmap_cache_examples.h
1/*
2 * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef _ADDRMAPCACHES_H
8#define _ADDRMAPCACHES_H
9
10#include <router.h>
11
12namespace gs {
13
14template <typename Key, typename Value>
15class LRUCache : public AddrMapCacheBase<Key, Value>
16{
17 const size_t Capacity = 0x10000; // 65,536 entries for address-based caching
18 using ListIt = typename std::list<std::pair<Key, Value>>::iterator;
19 std::list<std::pair<Key, Value>> m_list;
20 std::unordered_map<Key, ListIt> m_map;
21
22 // Statistics
23 uint64_t m_hits = 0;
24 uint64_t m_misses = 0;
25#if THREAD_SAFE == true
26 mutable std::shared_mutex m_mutex;
27#endif
28
29public:
36 bool get(const Key& key, Value& value) override
37 {
38#if THREAD_SAFE == true
39 std::unique_lock<std::shared_mutex> l(m_mutex);
40#endif
41 auto it = m_map.find(key);
42 if (it == m_map.end()) {
43 ++m_misses;
44 return false;
45 }
46
47 // Move to front (most recently used)
48 m_list.splice(m_list.begin(), m_list, it->second);
49 value = it->second->second;
50 ++m_hits;
51 return true;
52 }
53
59 void put(const Key& key, const Value& value, [[maybe_unused]] uint64_t size) override
60 {
61#if THREAD_SAFE == true
62 std::unique_lock<std::shared_mutex> l(m_mutex);
63#endif
64 // Evict least recently used entry if at capacity
65 if (m_list.size() >= Capacity) {
66 auto last = m_list.back();
67 m_map.erase(last.first);
68 m_list.pop_back();
69 }
70
71 // Insert new entry at front
72 m_list.emplace_front(key, value);
73 m_map[key] = m_list.begin();
74 }
75
77 void clear() override
78 {
79 m_list.clear();
80 m_map.clear();
81 }
82
83 // Statistics interface implementation
84 uint64_t get_hits() const override { return m_hits; }
85 uint64_t get_misses() const override { return m_misses; }
86 void reset_stats() override
87 {
88 m_hits = 0;
89 m_misses = 0;
90 }
91};
92
105template <typename Key, typename Value>
106class RegionFIFOCache : public AddrMapCacheBase<Key, Value>
107{
108 const size_t Capacity = 8; // Small capacity since each entry covers entire region
109 using ListIt = typename std::list<std::pair<Key, Value>>::iterator;
110 struct Entry {
111 Key start;
112 uint64_t end;
113 Value value;
114 };
115 std::vector<Entry> m_cache;
116
117 // Statistics
118 uint64_t m_hits = 0;
119 uint64_t m_misses = 0;
120#if THREAD_SAFE == true
121 mutable std::mutex m_mutex;
122#endif
123
124public:
125 bool get(const Key& key, Value& value) override
126 {
127#if THREAD_SAFE == true
128 std::lock_guard<std::mutex> l(m_mutex);
129#endif
130 for (const auto& entry : m_cache) {
131 if (key >= entry.start && key < entry.end) {
132 value = entry.value;
133 ++m_hits;
134 return true;
135 }
136 }
137 ++m_misses;
138 return false;
139 }
140
141 void put(const Key& key, const Value& value, [[maybe_unused]] uint64_t size) override
142 {
143#if THREAD_SAFE == true
144 std::lock_guard<std::mutex> l(m_mutex);
145#endif
146 (void)key; // Region cache uses canonical region start from the Value
147 (void)size; // Region cache uses the target's region size
148 if (!value) {
149 // Do not cache negative lookups for region caches
150 return;
151 }
152 if (m_cache.size() >= Capacity) {
153 m_cache.erase(m_cache.begin());
154 }
155 // Store canonical region bounds to ensure future lookups within the region hit
156 m_cache.emplace_back(Entry{ value->address, value->address + value->size, value });
157 }
158
159 void clear() override { m_cache.clear(); }
160
161 // Statistics interface implementation
162 uint64_t get_hits() const override { return m_hits; }
163 uint64_t get_misses() const override { return m_misses; }
164 void reset_stats() override
165 {
166 m_hits = 0;
167 m_misses = 0;
168 }
169};
170
192template <typename Key, typename Value>
193class RegionLRUCache : public AddrMapCacheBase<Key, Value>
194{
195 const size_t Capacity = 8; // Small capacity since each entry covers entire region
196
197 struct CacheEntry {
198 Key start; // Region start address (inclusive)
199 uint64_t end; // Region end address (exclusive)
200 Value target; // Target info pointer
201
202 CacheEntry(Key s, uint64_t e, Value t): start(s), end(e), target(t) {}
203 };
204
205 // Instance storage (each router has its own cache)
206 std::list<CacheEntry> m_list;
207 uint64_t m_hits = 0;
208 uint64_t m_misses = 0;
209#if THREAD_SAFE == true
210 mutable std::mutex m_mutex;
211#endif
212
213public:
225 bool get(const Key& key, Value& value) override
226 {
227#if THREAD_SAFE == true
228 std::lock_guard<std::mutex> l(m_mutex);
229#endif
230 // Traverse from MRU to LRU using a reverse walk over the list.
231 // When found, splice the node to the back (MRU) in O(1).
232 for (auto it = m_list.end(); it != m_list.begin();) {
233 --it;
234 const CacheEntry& entry = *it;
235 if (key >= entry.start && key < entry.end) {
236 value = entry.target;
237 if (std::next(it) != m_list.end()) {
238 m_list.splice(m_list.end(), m_list, it);
239 }
240 ++m_hits;
241 return true;
242 }
243 }
244 ++m_misses;
245 return false;
246 }
247
259 void put(const Key& key, const Value& value, uint64_t size) override
260 {
261#if THREAD_SAFE == true
262 std::lock_guard<std::mutex> l(m_mutex);
263#endif
264 (void)key; // Region cache ignores probe address
265 (void)size; // Region cache uses the target's region size
266 if (!value) {
267 // Do not cache negative lookups for region caches
268 return;
269 }
270
271 // Evict least recently used entry (front) if at capacity
272 if (m_list.size() >= Capacity) {
273 m_list.pop_front();
274 }
275
276 // Insert new entry at back (most recently used) using canonical region bounds
277 m_list.emplace_back(value->address, value->address + value->size, value);
278 }
279
281 void clear() override { m_list.clear(); }
282
283 // Statistics interface implementation
284 uint64_t get_hits() const override { return m_hits; }
285 uint64_t get_misses() const override { return m_misses; }
286 void reset_stats() override
287 {
288 m_hits = 0;
289 m_misses = 0;
290 }
291};
292} // namespace gs
293#endif // _ADDRMAPCACHES_H
Definition target.h:160
Definition router.h:57
Definition addrmap_cache_examples.h:16
void put(const Key &key, const Value &value, uint64_t size) override
Insert or update value in cache with LRU eviction.
Definition addrmap_cache_examples.h:59
bool get(const Key &key, Value &value) override
Retrieve value from cache and update LRU order.
Definition addrmap_cache_examples.h:36
void clear() override
Clear all cached entries.
Definition addrmap_cache_examples.h:77
RegionFIFOCache - A simple FIFO cache for region-based address lookups.
Definition addrmap_cache_examples.h:107
RegionLRUCache - A true LRU cache for region-based address lookups.
Definition addrmap_cache_examples.h:194
bool get(const Key &key, Value &value) override
Retrieve value from cache and update LRU order.
Definition addrmap_cache_examples.h:225
void put(const Key &key, const Value &value, uint64_t size) override
Insert or update region in cache with LRU eviction.
Definition addrmap_cache_examples.h:259
void clear() override
Clear all cached entries.
Definition addrmap_cache_examples.h:281
Tool which reads a Lua configuration file and sets parameters.
Definition biflow.cc:10