PIVX Core  5.6.99
P2P Digital Currency
unordered_lru_cache.h
Go to the documentation of this file.
1 // Copyright (c) 2019-2021 The Dash Core developers
2 // Copyright (c) 2023 The Dash Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #ifndef PIVX_UNORDERED_LRU_CACHE_H
7 #define PIVX_UNORDERED_LRU_CACHE_H
8 
9 #include <algorithm>
10 #include <cassert>
11 #include <cstdint>
12 #include <unordered_map>
13 #include <vector>
14 
15 template<typename Key, typename Value, typename Hasher, size_t MaxSize = 0, size_t TruncateThreshold = 0>
17 {
18 private:
19  typedef std::unordered_map<Key, std::pair<Value, int64_t>, Hasher> MapType;
20 
22  size_t maxSize;
24  int64_t accessCounter{0};
25 
26 public:
27  explicit unordered_lru_cache(size_t _maxSize = MaxSize, size_t _truncateThreshold = TruncateThreshold) : maxSize(_maxSize),
28  truncateThreshold(_truncateThreshold == 0 ? _maxSize * 2 : _truncateThreshold)
29  {
30  // either specify maxSize through template arguments or the constructor and fail otherwise
31  assert(_maxSize != 0);
32  }
33 
34  size_t max_size() const { return maxSize; }
35 
36  template<typename Value2>
37  void _emplace(const Key& key, Value2&& v)
38  {
39  auto it = cacheMap.find(key);
40  if (it == cacheMap.end()) {
41  cacheMap.emplace(key, std::make_pair(std::forward<Value2>(v), accessCounter++));
42  } else {
43  it->second.first = std::forward<Value2>(v);
44  it->second.second = accessCounter++;
45  }
47  }
48 
49  void emplace(const Key& key, Value&& v)
50  {
51  _emplace(key, v);
52  }
53 
54  void insert(const Key& key, const Value& v)
55  {
56  _emplace(key, v);
57  }
58 
59  bool get(const Key& key, Value& value)
60  {
61  auto it = cacheMap.find(key);
62  if (it != cacheMap.end()) {
63  it->second.second = accessCounter++;
64  value = it->second.first;
65  return true;
66  }
67  return false;
68  }
69 
70  bool exists(const Key& key)
71  {
72  auto it = cacheMap.find(key);
73  if (it != cacheMap.end()) {
74  it->second.second = accessCounter++;
75  return true;
76  }
77  return false;
78  }
79 
80  void erase(const Key& key)
81  {
82  cacheMap.erase(key);
83  }
84 
85  void clear()
86  {
87  cacheMap.clear();
88  }
89 
90 private:
92  {
93  typedef typename MapType::iterator Iterator;
94 
95  if (cacheMap.size() <= truncateThreshold) {
96  return;
97  }
98 
99  std::vector<Iterator> vec;
100  vec.reserve(cacheMap.size());
101  for (auto it = cacheMap.begin(); it != cacheMap.end(); ++it) {
102  vec.emplace_back(it);
103  }
104  // sort by last access time (descending order)
105  std::sort(vec.begin(), vec.end(), [](const Iterator& it1, const Iterator& it2) {
106  return it1->second.second > it2->second.second;
107  });
108 
109  for (size_t i = maxSize; i < vec.size(); i++) {
110  cacheMap.erase(vec[i]);
111  }
112  }
113 };
114 
115 #endif // PIVX_UNORDERED_LRU_CACHE_H
unordered_lru_cache(size_t _maxSize=MaxSize, size_t _truncateThreshold=TruncateThreshold)
bool get(const Key &key, Value &value)
bool exists(const Key &key)
void _emplace(const Key &key, Value2 &&v)
void erase(const Key &key)
void emplace(const Key &key, Value &&v)
std::unordered_map< Key, std::pair< Value, int64_t >, Hasher > MapType
void insert(const Key &key, const Value &v)