26#include <unordered_map>
29template <
typename Key,
typename Value>
class Cache {
31 std::unordered_map<Key, typename std::add_const<Value>::type>;
40 m_max_size = m_cache.max_size();
51 std::minstd_rand m_rand;
61 void drop_random_element() {
65 auto const bucket_count = m_cache.bucket_count();
71 std::uniform_int_distribution<size_type>{0, bucket_count - 1}(m_rand);
73 while (0 == m_cache.bucket_size(bucket)) {
75 bucket = ((bucket + 1) % bucket_count);
79 auto const elem_index = std::uniform_int_distribution<size_type>{
80 0, m_cache.bucket_size(bucket) - 1}(m_rand);
84 std::next(m_cache.cbegin(bucket),
static_cast<long>(elem_index))->first;
87 m_cache.erase(drop_key);
98 bool has(Key
const &k)
const {
return m_cache.find(k) != m_cache.end(); }
112 template <
typename ValueRef> Value
const *
put(Key
const &k, ValueRef &&v) {
113 auto check_for_k =
true;
118 if ((m_cache.size() >= m_max_size) && !
has(k)) {
119 drop_random_element();
123 if (check_for_k &&
has(k)) {
127 typename map_type::const_iterator it;
128 std::tie(it, std::ignore) = m_cache.emplace(k, std::forward<ValueRef>(v));
130 return &(it->second);
148 template <
typename KeyInputIterator,
typename ValueInputIterator>
149 KeyInputIterator
put(KeyInputIterator kbegin, KeyInputIterator kend,
150 ValueInputIterator vbegin) {
151 auto const range_len = std::distance(kbegin, kend);
152 auto const size_max =
static_cast<decltype(range_len)
>(
max_size());
153 auto const len = (range_len > size_max) ? size_max : range_len;
154 kend = std::next(kbegin, len);
157 while (
static_cast<decltype(len)
>(
max_size() -
size()) < len) {
158 drop_random_element();
161 while (kbegin != kend) {
162 put(*kbegin++, *vbegin++);
174 Value
const *
get(Key
const &k)
const {
175 auto const needle = m_cache.find(k);
177 if (m_cache.end() != needle) {
178 return &(needle->second);
bool has(Key const &k) const
Query if k is contained in the cache.
void invalidate()
Clear the cache.
typename map_type::size_type size_type
size_type size() const
Number of elements currently cached.
Cache(size_type max_size)
KeyInputIterator put(KeyInputIterator kbegin, KeyInputIterator kend, ValueInputIterator vbegin)
Put a range of values into the cache.
Value const * put(Key const &k, ValueRef &&v)
Put a value into the cache.
Value const * get(Key const &k) const
Get a value.
size_type max_size() const
Maximal size of the cache.