41 #include <unordered_map>
68 class KeyNotFound :
public std::invalid_argument
71 KeyNotFound() : std::invalid_argument(
"key_not_found")
76 template <
typename K,
typename V>
struct KeyValuePair
82 KeyValuePair(
const K &k,
const V &v) : key(k), value(v)
86 KeyValuePair(
const K &k, V &&v) : key(k), value(std::move(v))
103 template <
class Key,
class Value,
class Lock = NullLock,
104 class Map = std::unordered_map<
105 Key,
typename std::list<KeyValuePair<Key, Value>>::iterator>>
109 typedef KeyValuePair<Key, Value> node_type;
110 typedef std::list<KeyValuePair<Key, Value>> list_type;
111 typedef Map map_type;
112 typedef Lock lock_type;
113 using Guard = std::lock_guard<lock_type>;
123 explicit Cache(
size_t maxSize = 64,
size_t elasticity = 10)
124 : maxSize_(maxSize), elasticity_(elasticity)
128 virtual ~Cache() =
default;
133 return cache_.size();
139 return cache_.empty();
149 void insert(
const Key &k,
const Value &v)
152 const auto iter = cache_.find(k);
153 if (iter != cache_.end())
155 iter->second->value = v;
156 keys_.splice(keys_.begin(), keys_, iter->second);
160 keys_.emplace_front(k, v);
161 cache_[k] = keys_.begin();
165 Value &insert(
const Key &k, Value &&v)
168 const auto iter = cache_.find(k);
169 if (iter != cache_.end())
171 iter->second->value = std::move(v);
172 keys_.splice(keys_.begin(), keys_, iter->second);
173 return keys_.front().value;
176 keys_.emplace_front(k, std::move(v));
177 cache_[k] = keys_.begin();
179 return keys_.front().value;
182 bool tryGet(
const Key &kIn, Value &vOut)
185 const auto iter = cache_.find(kIn);
186 if (iter == cache_.end())
190 keys_.splice(keys_.begin(), keys_, iter->second);
191 vOut = iter->second->value;
199 const Value &get(
const Key &k)
202 const auto iter = cache_.find(k);
203 if (iter == cache_.end())
207 keys_.splice(keys_.begin(), keys_, iter->second);
208 return iter->second->value;
211 Value *getPtr(
const Key &k)
214 const auto iter = cache_.find(k);
215 if (iter == cache_.end())
219 keys_.splice(keys_.begin(), keys_, iter->second);
220 return &(iter->second->value);
226 Value getCopy(
const Key &k)
231 bool remove(
const Key &k)
234 auto iter = cache_.find(k);
235 if (iter == cache_.end())
239 keys_.erase(iter->second);
244 bool contains(
const Key &k)
247 return cache_.find(k) != cache_.end();
250 bool getOldestEntry(Key &kOut, Value &vOut)
257 kOut = keys_.back().key;
258 vOut = keys_.back().value;
262 bool removeAndRecycleOldestEntry(Value &vOut)
269 vOut = std::move(keys_.back().value);
270 cache_.erase(keys_.back().key);
275 size_t getMaxSize()
const
280 size_t getElasticity()
const
285 size_t getMaxAllowedSize()
const
287 return maxSize_ + elasticity_;
290 template <
typename F>
void cwalk(
F &f)
const
293 std::for_each(keys_.begin(), keys_.end(), f);
297 : cache_(std::move(other.cache_)), keys_(std::move(other.keys_)),
298 maxSize_(other.maxSize_), elasticity_(other.elasticity_)
305 size_t maxAllowed = maxSize_ + elasticity_;
306 if (maxSize_ == 0 || cache_.size() <= maxAllowed)
311 while (cache_.size() > maxSize_)
313 cache_.erase(keys_.back().key);
322 Cache(
const Cache &) =
delete;
323 Cache &operator=(
const Cache &) =
delete;
325 mutable Lock lock_{};