|
|
|
@ -2,12 +2,16 @@ |
|
|
|
|
|
|
|
#include <list> |
|
|
|
#include <unordered_map> |
|
|
|
#include <optional> |
|
|
|
|
|
|
|
template<typename KeyType, typename ValueType> |
|
|
|
class LRUCache { |
|
|
|
public: |
|
|
|
explicit LRUCache(size_t capacity) : capacity(capacity) {} |
|
|
|
explicit LRUCache(size_t capacity) : capacity(capacity) { |
|
|
|
cache_map.reserve(capacity); |
|
|
|
} |
|
|
|
|
|
|
|
// Returns pointer to value if found, nullptr otherwise |
|
|
|
ValueType* get(const KeyType& key) { |
|
|
|
auto it = cache_map.find(key); |
|
|
|
if (it == cache_map.end()) { |
|
|
|
@ -19,6 +23,13 @@ public: |
|
|
|
return &(it->second.second); |
|
|
|
} |
|
|
|
|
|
|
|
// Returns pointer to value if found (without promoting it), nullptr otherwise |
|
|
|
ValueType* peek(const KeyType& key) const { |
|
|
|
auto it = cache_map.find(key); |
|
|
|
return it != cache_map.end() ? &(it->second.second) : nullptr; |
|
|
|
} |
|
|
|
|
|
|
|
// Inserts or updates a key-value pair |
|
|
|
void put(const KeyType& key, const ValueType& value) { |
|
|
|
auto it = cache_map.find(key); |
|
|
|
|
|
|
|
@ -41,15 +52,56 @@ public: |
|
|
|
cache_map[key] = {cache_list.begin(), value}; |
|
|
|
} |
|
|
|
|
|
|
|
// Attempts to get value, returns std::nullopt if not found |
|
|
|
std::optional<ValueType> try_get(const KeyType& key) { |
|
|
|
auto* val = get(key); |
|
|
|
return val ? std::optional<ValueType>(*val) : std::nullopt; |
|
|
|
} |
|
|
|
|
|
|
|
// Checks if key exists in cache |
|
|
|
bool contains(const KeyType& key) const { |
|
|
|
return cache_map.find(key) != cache_map.end(); |
|
|
|
} |
|
|
|
|
|
|
|
// Removes a key from the cache if it exists |
|
|
|
bool erase(const KeyType& key) { |
|
|
|
auto it = cache_map.find(key); |
|
|
|
if (it == cache_map.end()) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
cache_list.erase(it->second.first); |
|
|
|
cache_map.erase(it); |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
// Removes all elements from the cache |
|
|
|
void clear() { |
|
|
|
cache_map.clear(); |
|
|
|
cache_list.clear(); |
|
|
|
} |
|
|
|
|
|
|
|
// Returns current number of elements in cache |
|
|
|
size_t size() const { |
|
|
|
return cache_map.size(); |
|
|
|
} |
|
|
|
|
|
|
|
// Returns maximum capacity of cache |
|
|
|
size_t get_capacity() const { |
|
|
|
return capacity; |
|
|
|
} |
|
|
|
|
|
|
|
// Resizes the cache, evicting LRU items if new capacity is smaller |
|
|
|
void resize(size_t new_capacity) { |
|
|
|
capacity = new_capacity; |
|
|
|
while (cache_map.size() > capacity) { |
|
|
|
auto last = cache_list.back(); |
|
|
|
cache_map.erase(last); |
|
|
|
cache_list.pop_back(); |
|
|
|
} |
|
|
|
cache_map.reserve(capacity); |
|
|
|
} |
|
|
|
|
|
|
|
private: |
|
|
|
size_t capacity; |
|
|
|
std::list<KeyType> cache_list; |
|
|
|
|