onion-wownero-blockchain-ex.../ext/vpetrigocaches/cache.hpp

139 lines
2.6 KiB
C++
Raw Normal View History

#ifndef CACHE_HPP
#define CACHE_HPP
#include <cstddef>
#include <limits>
#include <memory>
#include <mutex>
#include <unordered_map>
#include "cache_policy.hpp"
namespace caches
{
// Base class for caching algorithms
template <typename Key, typename Value, typename Policy = NoCachePolicy<Key>>
class fixed_sized_cache
{
public:
using iterator = typename std::unordered_map<Key, Value>::iterator;
using const_iterator =
typename std::unordered_map<Key, Value>::const_iterator;
using operation_guard = typename std::lock_guard<std::mutex>;
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<size_t>::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<Key, Value> cache_items_map;
mutable Policy cache_policy;
mutable std::mutex safe_op;
size_t max_cache_size;
};
}
#endif // CACHE_HPP