1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| #pragma once #include <list> #include <unordered_map> #include <mutex> #include <memory>
template <typename K, typename V> class LRUCache { private: using Cache = std::list<std::pair<K, V>>; Cache cache; std::unordered_map<K, typename Cache::iterator> um; const size_t capacity; std::unique_ptr<std::mutex> mtx;
public: LRUCache(size_t capacity) : capacity(capacity),mtx{new std::mutex()} {}
template <typename K1> V *get(K1 &&key) { std::unique_lock<std::mutex> ul{*mtx}; auto it = um.find(std::forward<K1>(key)); if (it == um.end()) { return nullptr; } cache.splice(cache.end(), cache, it->second); return &it->second->second; }
template <typename K1, typename V1> void put(K1 &&key, V1 &&value) { if (capacity == 0) { return; }
std::unique_lock<std::mutex> ul{*mtx}; auto it = um.find(std::forward<K1>(key)); if (it == um.end()) { if (cache.size() == capacity) { um.erase(cache.front().first); cache.pop_front(); }
auto cache_it = cache.emplace(cache.end(), std::forward<K1>(key), std::forward<V1>(value)); um.emplace(cache_it->first, cache_it); } else { it->second->second = std::forward<V1>(value); cache.splice(cache.end(), cache, it->second); } } };
|