forked from miki151/keeperrl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
call_cache.h
58 lines (50 loc) · 1.31 KB
/
call_cache.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#pragma once
#include "stdafx.h"
#include "hashing.h"
#include "util.h"
template <typename Value>
class CallCache {
public:
CallCache(int size) : maxSize(size) {}
typedef pair<int, int> Key;
template <typename... Args, typename Generator>
Value get(Generator gen, int id, Args&&...args) {
Key key = {id, combineHash(args...)};
if (auto elem = getValue(key))
return *elem;
else
return insertValue(key, gen(std::forward<Args>(args)...));
}
int getSize() const {
return cache.size();
}
template <typename... Args>
bool contains(int id, Args...args) {
return cache.count({id, combineHash(args...)});
}
private:
Value& insertValue(Key key, Value value) {
if (cache.size() >= maxSize) {
CHECK(!lastUsed.isEmpty());
pair<const int, Key> lru = lastUsed.getFront2();
lastUsed.erase(lru.first);
cache.erase(lru.second);
}
if (lastUsed.contains(key))
lastUsed.erase(key);
lastUsed.insert(key, ++cnt);
return cache[key] = value;
}
optional<Value&> getValue(Key key) {
if (auto elem = getReferenceMaybe(cache, key)) {
lastUsed.erase(key);
lastUsed.insert(key, ++cnt);
return *elem;
} else
return none;
}
const int maxSize;
HashMap<Key, Value> cache;
BiMap<Key, int> lastUsed;
int cnt = 0;
};