14 #if __has_include(<ankerl/unordered_dense.h>)
15 #include <ankerl/unordered_dense.h>
17 template <
typename Key,
typename Value>
18 using unordered_map = ankerl::unordered_dense::map<Key, Value>;
21 #include <unordered_map>
23 template <
typename Key,
typename Value>
34 template <
typename Key,
typename Entry>
39 : nentries_(nentries),
40 entry_initial_state_(e),
41 entries_(init_entries()),
43 table_(init_table()) {}
48 return table_.find(key) != table_.end();
51 template <
bool UpdateLRU = true>
53 auto it = table_.find(key);
54 if (it == table_.end()) {
56 cache_entry& ce = entries_[idx];
58 ce.entry.on_cache_map(idx);
63 if constexpr (UpdateLRU) {
69 cache_entry& ce = entries_[idx];
70 if constexpr (UpdateLRU) {
78 auto it = table_.find(key);
79 if (it != table_.end()) {
81 cache_entry& ce = entries_[idx];
85 ce.entry = entry_initial_state_;
91 template <
typename Func>
93 for (
auto& ce : entries_) {
106 typename std::list<cache_entry_idx_t>::iterator lru_it;
108 cache_entry(
const Entry& e) : entry(e) {}
111 std::vector<cache_entry> init_entries() {
112 std::vector<cache_entry> entries;
114 cache_entry& ce = entries.emplace_back(entry_initial_state_);
115 ce.allocated =
false;
121 std::list<cache_entry_idx_t> init_lru() {
122 std::list<cache_entry_idx_t> lru;
123 for (
auto& ce : entries_) {
124 lru.push_back(ce.idx);
125 ce.lru_it = std::prev(lru.end());
131 unordered_map<Key, cache_entry_idx_t> init_table() {
132 unordered_map<Key, cache_entry_idx_t> table;
134 table.reserve(nentries_);
138 void move_to_back_lru(cache_entry& ce) {
139 lru_.splice(lru_.end(), lru_, ce.lru_it);
140 ITYR_CHECK(std::prev(lru_.end()) == ce.lru_it);
146 for (
const auto& idx : lru_) {
147 cache_entry& ce = entries_[idx];
151 if (ce.entry.is_evictable()) {
152 Key prev_key = ce.key;
153 table_.erase(prev_key);
155 ce.allocated =
false;
159 throw cache_full_exception{};
163 Entry entry_initial_state_;
164 std::vector<cache_entry> entries_;
165 std::list<cache_entry_idx_t> lru_;
166 unordered_map<Key, cache_entry_idx_t> table_;
169 ITYR_TEST_CASE(
"[ityr::ori::cache_system] testing cache system") {
172 bool evictable =
true;
175 bool is_evictable()
const {
return evictable; }
181 cache_system<key_t, test_entry> cs(nelems);
184 std::vector<key_t> keys;
185 for (
int i = 0; i < nkey; i++) {
190 for (key_t k : keys) {
191 test_entry& e = cs.ensure_cached(k);
193 for (
int i = 0; i < 10; i++) {
194 test_entry& e2 = cs.ensure_cached(k);
200 ITYR_SUBCASE(
"all entries should be cached when the number of entries is small enough") {
201 for (
int i = 0; i < nelems; i++) {
202 cs.ensure_cached(keys[i]);
205 for (
int i = 0; i < nelems; i++) {
206 cs.ensure_cached(keys[i]);
208 for (
int j = 0; j < nelems; j++) {
214 ITYR_SUBCASE(
"nonevictable entries should not be evicted") {
216 for (
int i = 0; i < nrem; i++) {
217 test_entry& e = cs.ensure_cached(keys[i]);
221 for (key_t k : keys) {
224 for (
int j = 0; j < nrem; j++) {
228 for (
int i = 0; i < nrem; i++) {
229 test_entry& e = cs.ensure_cached(keys[i]);
235 ITYR_SUBCASE(
"should throw exception if cache is full") {
236 for (
int i = 0; i < nelems; i++) {
237 test_entry& e = cs.ensure_cached(keys[i]);
242 for (
int i = 0; i < nelems; i++) {
243 test_entry& e = cs.ensure_cached(keys[i]);
247 cs.ensure_cached(keys[nelems]);
252 for (
int i = 0; i < nkey; i++) {
253 cs.ensure_cached(keys[i]);
255 for (
int j = 0; j <= i - nelems; j++) {
258 for (
int j =
std::max(0, i - nelems + 1); j < i; j++) {
264 for (key_t k : keys) {
265 cs.ensure_evicted(k);
Definition: cache_system.hpp:32
Definition: cache_system.hpp:35
cache_system(cache_entry_idx_t nentries, const Entry &e)
Definition: cache_system.hpp:38
void for_each_entry(Func &&f)
Definition: cache_system.hpp:92
cache_system(cache_entry_idx_t nentries)
Definition: cache_system.hpp:37
bool is_cached(Key key) const
Definition: cache_system.hpp:47
cache_entry_idx_t num_entries() const
Definition: cache_system.hpp:45
Entry & ensure_cached(Key key)
Definition: cache_system.hpp:52
void ensure_evicted(Key key)
Definition: cache_system.hpp:77
#define ITYR_CHECK_THROWS_AS(exp, exception)
Definition: util.hpp:51
#define ITYR_SUBCASE(name)
Definition: util.hpp:41
#define ITYR_CHECK(cond)
Definition: util.hpp:48
Definition: block_region_set.hpp:9
std::unordered_map< Key, Value > unordered_map
Definition: cache_system.hpp:24
int cache_entry_idx_t
Definition: cache_system.hpp:30
monoid< T, max_functor<>, lowest< T > > max
Definition: reducer.hpp:104