#ifndef CACHE_HPP #define CACHE_HPP #include #include #include #include #include #include "cache_policy.hpp" namespace caches { // Base class for caching algorithms template > class fixed_sized_cache { public: using iterator = typename std::unordered_map::iterator; using const_iterator = typename std::unordered_map::const_iterator; using operation_guard = typename std::lock_guard; fixed_sized_cache( size_t max_size, const Policy& policy = Policy()) : max_cache_size{max_size}, cache_policy(policy) { if (max_cache_size == 0) { max_cache_size = std::numeric_limits::max(); } } void Put(const Key& key, const Value& value) { operation_guard{safe_op}; auto elem_it = FindElem(key); if (elem_it == cache_items_map.end()) { // add new element to the cache if (Size() + 1 > max_cache_size) { auto disp_candidate_key = cache_policy.ReplCandidate(); Erase(disp_candidate_key); } Insert(key, value); } else { // update previous value Update(key, value); } } bool Contains(const Key& key) { operation_guard{safe_op}; auto elem_it = FindElem(key); return elem_it != cache_items_map.end(); } const Value& Get(const Key& key) const { operation_guard{safe_op}; auto elem_it = FindElem(key); if (elem_it == cache_items_map.end()) { throw std::range_error{"No such element in the cache"}; } cache_policy.Touch(key); return elem_it->second; } const size_t Size() const { operation_guard{safe_op}; return cache_items_map.size(); } // return a key of a displacement candidate void Clear() { operation_guard{safe_op}; cache_policy.Clear(); cache_items_map.clear(); } protected: void Insert(const Key& key, const Value& value) { cache_policy.Insert(key); cache_items_map.emplace(std::make_pair(key, value)); } void Erase(const Key& key) { cache_policy.Erase(key); cache_items_map.erase(key); } void Update(const Key& key, const Value& value) { cache_policy.Touch(key); cache_items_map[key] = value; } const_iterator FindElem(const Key& key) const { return cache_items_map.find(key); } private: std::unordered_map cache_items_map; mutable Policy cache_policy; mutable std::mutex safe_op; size_t max_cache_size; }; } #endif // CACHE_HPP