FastLED 3.9.15
Loading...
Searching...
No Matches
unordered_map_lru.h
Go to the documentation of this file.
1#pragma once
2
3/*
4LRU (Least Recently Used) unordered_map that is optimized for embedded devices.
5This unordered_map has a maximum size and will automatically evict the least
6recently used items when it reaches capacity.
7*/
8
10#include "fl/stl/type_traits.h"
11#include "fl/stl/hash.h"
12#include "fl/stl/limits.h"
13#include "fl/stl/int.h"
15#include "fl/stl/noexcept.h"
16
17namespace fl {
18
19template <typename Key, typename T, typename Hash = Hash<Key>,
20 typename KeyEqual = EqualTo<Key>,
21 int INLINED_COUNT = FASTLED_HASHMAP_INLINED_COUNT>
23 private:
24 // Wrapper for values that includes access time tracking
33
34 public:
36 // Ensure max size is at least 1
37 if (mMaxSize < 1)
38 mMaxSize = 1;
39 }
40
41 HashMapLru(fl::size max_size, memory_resource* resource)
42 : mMap(resource), mMaxSize(max_size), mCurrentTime(0) {
43 if (mMaxSize < 1)
44 mMaxSize = 1;
45 }
46
47 void setMaxSize(fl::size max_size) {
48 while (mMaxSize < max_size) {
49 // Evict oldest items until we reach the new max size
51 }
53 }
54
55 void swap(HashMapLru &other) {
56 fl::swap(mMap, other.mMap);
59 }
60
61 // Insert or update a key-value pair
62 void insert(const Key &key, const T &value) {
63 // Only evict if we're at capacity AND this is a new key
64 const ValueWithTimestamp *existing = mMap.find_value(key);
65
66 auto curr = mCurrentTime++;
67
68 if (existing) {
69 // Update the value and access time
70 ValueWithTimestamp &vwt =
71 const_cast<ValueWithTimestamp &>(*existing);
72 vwt.value = value;
73 vwt.last_access_time = curr;
74 return;
75 }
76 if (mMap.size() >= mMaxSize) {
78 }
79
80 // Insert or update the value with current timestamp
81 ValueWithTimestamp vwt(value, mCurrentTime);
82 mMap.insert(key, vwt);
83 }
84
85 // Get value for key, returns nullptr if not found
86 T *find_value(const Key &key) {
87 ValueWithTimestamp *vwt = mMap.find_value(key);
88 if (vwt) {
89 // Update access time
90 auto curr = mCurrentTime++;
91 vwt->last_access_time = curr;
92 return &vwt->value;
93 }
94 return nullptr;
95 }
96
97 // Get value for key, returns nullptr if not found (const version)
98 const T *find_value(const Key &key) const {
99 const ValueWithTimestamp *vwt = mMap.find_value(key);
100 return vwt ? &vwt->value : nullptr;
101 }
102
103 // Access operator - creates entry if not exists
104 T &operator[](const Key &key) {
105 // If we're at capacity and this is a new key, evict oldest
106 auto curr = mCurrentTime++;
107
108 auto entry = mMap.find_value(key);
109 if (entry) {
110 // Update access time
111 entry->last_access_time = curr;
112 return entry->value;
113 }
114
115 if (mMap.size() >= mMaxSize) {
116 evictOldest();
117 }
118
119 // Get or create entry and update timestamp
120 // mCurrentTime++;
121 ValueWithTimestamp &vwt = mMap[key];
122 vwt.last_access_time = curr;
123 return vwt.value;
124 }
125
126 // Remove a key
127 bool remove(const Key &key) { return mMap.remove(key); }
128
129 // Clear the map
130 void clear() {
131 mMap.clear();
132 mCurrentTime = 0;
133 }
134
135 // Size accessors
136 fl::size size() const { return mMap.size(); }
137 bool empty() const { return mMap.empty(); }
138 fl::size capacity() const { return mMaxSize; }
139 memory_resource* get_memory_resource() const { return mMap.get_memory_resource(); }
140
141 private:
142 // Evict the least recently used item
143 void evictOldest() {
144 if (mMap.empty())
145 return;
146
147 // Find the entry with the oldest timestamp
148 Key oldest_key;
149 // Use (max)() to prevent macro expansion by Arduino.h's max macro
150 u32 oldest_time = (fl::numeric_limits<u32>::max)();
151 bool found = false;
152
153 for (auto it = mMap.begin(); it != mMap.end(); ++it) {
154 const auto &entry = *it;
155 const ValueWithTimestamp &vwt = entry.second;
156
157 if (vwt.last_access_time < oldest_time) {
158 oldest_time = vwt.last_access_time;
159 oldest_key = entry.first;
160 found = true;
161 }
162 }
163
164 // Remove the oldest entry
165 if (found) {
166 mMap.remove(oldest_key);
167 }
168 }
169
171 fl::size mMaxSize;
173};
174
175} // namespace fl
memory_resource * get_memory_resource() const
fl::size size() const
T & operator[](const Key &key)
fl::size capacity() const
HashMapLru(fl::size max_size, memory_resource *resource)
unordered_map< Args, ValueWithTimestamp, Hash< Args >, EqualTo< Args >, FASTLED_HASHMAP_INLINED_COUNT > mMap
T * find_value(const Key &key)
void insert(const Key &key, const T &value)
void swap(HashMapLru &other)
HashMapLru(fl::size max_size)
bool remove(const Key &key)
const T * find_value(const Key &key) const
void setMaxSize(fl::size max_size)
Polymorphic memory resource base class (PMR-style).
PMR-style polymorphic memory resource for type-erased allocation.
void swap(T &a, T &b) FL_NOEXCEPT
Definition s16x16x4.h:877
constexpr int type_rank< T >::value
fl::u64 time() FL_NOEXCEPT
Alias for millis64() - returns 64-bit millisecond time.
Definition chrono.h:346
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NOEXCEPT
Definition Keyboard.h:22
ValueWithTimestamp(const T &v, u32 time)
static constexpr T max() FL_NOEXCEPT
Definition limits.h:108