Grok 20.3.2
LRUCache.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016-2026 Grok Image Compression Inc.
3 *
4 * This source code is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License, version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This source code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Affero General Public License for more details.
12 *
13 * You should have received a copy of the GNU Affero General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18#pragma once
19
20#include <list>
21#include <unordered_map>
22#include <mutex>
23#include <cstddef>
24#include <functional>
25#include <optional>
26#include <utility>
27
28namespace grk
29{
30
42template<typename Key, typename Value>
44{
45public:
46 using SizeFunc = std::function<size_t(const Value&)>;
47 using EvictFunc = std::function<void(const Key&, Value&&)>;
48
55 LRUCache(size_t maxBytes, SizeFunc sizeFunc, EvictFunc evictFunc = nullptr)
56 : maxBytes_(maxBytes), currentBytes_(0), sizeFunc_(std::move(sizeFunc)),
57 evictFunc_(std::move(evictFunc))
58 {}
59
60 ~LRUCache() = default;
61
62 // non-copyable, moveable
63 LRUCache(const LRUCache&) = delete;
64 LRUCache& operator=(const LRUCache&) = delete;
65 LRUCache(LRUCache&&) = default;
67
73 void put(const Key& key, Value value)
74 {
75 std::lock_guard<std::mutex> lock(mutex_);
76
77 auto it = map_.find(key);
78 if(it != map_.end())
79 {
80 // Update existing entry: remove old size, move to front
81 currentBytes_ -= sizeFunc_(it->second->second);
82 list_.erase(it->second);
83 map_.erase(it);
84 }
85
86 size_t entrySize = sizeFunc_(value);
87 list_.emplace_front(key, std::move(value));
88 map_[key] = list_.begin();
89 currentBytes_ += entrySize;
90
92 }
93
100 Value* get(const Key& key)
101 {
102 std::lock_guard<std::mutex> lock(mutex_);
103
104 auto it = map_.find(key);
105 if(it == map_.end())
106 return nullptr;
107
108 // Move to front (most recently used)
109 list_.splice(list_.begin(), list_, it->second);
110 return &(it->second->second);
111 }
112
116 bool contains(const Key& key) const
117 {
118 std::lock_guard<std::mutex> lock(mutex_);
119 return map_.find(key) != map_.end();
120 }
121
125 bool erase(const Key& key)
126 {
127 std::lock_guard<std::mutex> lock(mutex_);
128 auto it = map_.find(key);
129 if(it == map_.end())
130 return false;
131
132 currentBytes_ -= sizeFunc_(it->second->second);
133 list_.erase(it->second);
134 map_.erase(it);
135 return true;
136 }
137
141 void clear()
142 {
143 std::lock_guard<std::mutex> lock(mutex_);
144 list_.clear();
145 map_.clear();
146 currentBytes_ = 0;
147 }
148
149 size_t size() const
150 {
151 std::lock_guard<std::mutex> lock(mutex_);
152 return map_.size();
153 }
154
155 size_t currentBytes() const
156 {
157 std::lock_guard<std::mutex> lock(mutex_);
158 return currentBytes_;
159 }
160
161 size_t maxBytes() const
162 {
163 return maxBytes_;
164 }
165
167 {
168 std::lock_guard<std::mutex> lock(mutex_);
171 }
172
173private:
175 {
176 while(maxBytes_ > 0 && currentBytes_ > maxBytes_ && !list_.empty())
177 {
178 auto& back = list_.back();
179 size_t entrySize = sizeFunc_(back.second);
180 if(evictFunc_)
181 evictFunc_(back.first, std::move(back.second));
182 map_.erase(back.first);
183 list_.pop_back();
184 currentBytes_ -= entrySize;
185 }
186 }
187
188 using ListType = std::list<std::pair<Key, Value>>;
189
190 size_t maxBytes_;
194 ListType list_; // front = MRU, back = LRU
195 std::unordered_map<Key, typename ListType::iterator> map_; // key → list iterator
196 mutable std::mutex mutex_;
197};
198
199} // namespace grk
size_t size() const
Definition LRUCache.h:149
bool erase(const Key &key)
Remove a specific entry.
Definition LRUCache.h:125
void setMaxBytes(size_t maxBytes)
Definition LRUCache.h:166
LRUCache & operator=(LRUCache &&)=default
std::mutex mutex_
Definition LRUCache.h:196
std::function< void(const Key &, Value &&)> EvictFunc
Definition LRUCache.h:47
LRUCache & operator=(const LRUCache &)=delete
size_t currentBytes() const
Definition LRUCache.h:155
size_t maxBytes() const
Definition LRUCache.h:161
size_t maxBytes_
Definition LRUCache.h:190
LRUCache(const LRUCache &)=delete
size_t currentBytes_
Definition LRUCache.h:191
SizeFunc sizeFunc_
Definition LRUCache.h:192
EvictFunc evictFunc_
Definition LRUCache.h:193
std::function< size_t(const Value &)> SizeFunc
Definition LRUCache.h:46
std::list< std::pair< Key, Value > > ListType
Definition LRUCache.h:188
~LRUCache()=default
LRUCache(size_t maxBytes, SizeFunc sizeFunc, EvictFunc evictFunc=nullptr)
Construct an LRU cache.
Definition LRUCache.h:55
LRUCache(LRUCache &&)=default
void evictWhileOverCapacity()
Definition LRUCache.h:174
void put(const Key &key, Value value)
Insert or update an entry.
Definition LRUCache.h:73
Value * get(const Key &key)
Look up an entry.
Definition LRUCache.h:100
bool contains(const Key &key) const
Check if a key exists without promoting it in the LRU order.
Definition LRUCache.h:116
void clear()
Clear all entries.
Definition LRUCache.h:141
std::unordered_map< Key, typename ListType::iterator > map_
Definition LRUCache.h:195
ListType list_
Definition LRUCache.h:194
ResWindow.
Definition CompressedChunkCache.h:36