1#ifndef STORAGE_LRU_CACHE_H
2#define STORAGE_LRU_CACHE_H
5#include <unordered_map>
10#include <vkdb/concepts.h>
19template <RegularNoCVRefQuals TKey, RegularNoCVRefQuals TValue>
22 using key_type = TKey;
23 using mapped_type = std::optional<TValue>;
24 using value_type = std::pair<const key_type, mapped_type>;
25 using size_type = uint64_t;
32 : capacity_{DEFAULT_CAPACITY}
33 , mutex_{std::make_unique<std::mutex>()} {}
44 , mutex_{
std::make_unique<
std::mutex>()} {
46 throw std::invalid_argument{
47 "LRUCache(): Capacity must be greater than 0."
93 void put(K&& key, V&& value) {
94 std::lock_guard lock{*mutex_};
95 const auto it{map_.find(key)};
96 if (it != map_.end()) {
97 it->second->second = std::forward<V>(value);
98 list_.splice(list_.begin(), list_, it->second);
103 list_.emplace_front(std::forward<K>(key), std::forward<V>(value));
104 map_.try_emplace(list_.front().first, list_.begin());
114 template <SameNoCVRefQuals <key_type> K>
115 [[nodiscard]] mapped_type
get(K&& key) {
116 std::lock_guard lock{*mutex_};
117 const auto it{map_.find(std::forward<K>(key))};
118 if (it == map_.end()) {
121 list_.splice(list_.begin(), list_, it->second);
122 return it->second->second;
133 template <SameNoCVRefQuals <key_type> K>
134 [[nodiscard]]
bool contains(K&& key)
const noexcept {
135 std::lock_guard lock{*mutex_};
136 return map_.find(std::forward<K>(key)) != map_.end();
145 [[nodiscard]] size_type
capacity() const noexcept {
146 std::lock_guard lock{*mutex_};
155 [[nodiscard]] size_type
size() const noexcept {
156 std::lock_guard lock{*mutex_};
165 std::lock_guard lock{*mutex_};
175 using CacheList = std::list<value_type>;
181 using CacheListIter =
typename CacheList::iterator;
187 using CacheListIterMap = std::unordered_map<key_type, CacheListIter>;
193 static constexpr size_type DEFAULT_CAPACITY{1'000};
199 void evict_if_needed() noexcept {
200 if (list_.size() == capacity_) {
201 map_.erase(list_.back().first);
222 CacheListIterMap map_;
228 mutable std::unique_ptr<std::mutex> mutex_;
LRUCache() noexcept
Construct a new LRUCache object.
void put(K &&key, V &&value)
Put a key-value pair into the cache.
LRUCache(LRUCache &&) noexcept=default
Move-construct a LRUCache object.
bool contains(K &&key) const noexcept
Check if the cache contains a key.
mapped_type get(K &&key)
Get a value from the cache.
size_type size() const noexcept
Get the size of the cache.
size_type capacity() const noexcept
Remove a key from the cache.
LRUCache(size_type capacity)
Construct a new LRUCache object given a capacity.
void clear() noexcept
Clear the cache.
Concept for types that are the same after removing cv- and ref-qualifiers.