-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLRUCache.cpp
More file actions
118 lines (93 loc) · 2.35 KB
/
LRUCache.cpp
File metadata and controls
118 lines (93 loc) · 2.35 KB
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
template <class K, class T>
class LRUCacheEntry {
K key;
T data;
LRUCacheEntry* prev;
LRUCacheEntry* next;
};
typedef hash_map unordered_map;
template <class K, class T>
class LRUCache {
//Map of Key to LRUCacheEntry* of one node
hash_map<K,LRUCacheEntry<K,T>*> _mapping;
//PreAllocated CacheEntries - keeps track of MRU's
vector< LRUCacheEntry<K,T>* > _freeEntries;
//Doubly Linked List
LRUCacheEntry<K,T>* head;
LRUCacheEntry<K,T>* tail;
LRUCacheEntry<K,T>* entries;
public:
LRUCache(int capacity) {
entries = new LRUCacheEntry<K,T>[capacity];
for (unsigned int i = 0; i < capacity; ++i ) {
_freeEntries.push_back(entries+i);
}
head = tail = new LRUCacheEntry;
head->next = tail;
tail->prev = head;
head->prev = NULL;
tail->prev = NULL;
}
~LRUCache() {
delete entries[];
delete head;
delete tail;
_freeEntries.clear();
}
void put(K key, T data){
//First hash the key and get location in cache
LRUCacheEntry<K,T>* node = _mapping[key]
if (node) {
//detach, update data anyway, attach
_detach(node);
node->data = data();
_attach(node);
} else{
if (_freeEntries.empty()){
//LRU algorithm
//No free entries - detach from the tail of list
node = tail->prev;
_detach(node);
_mapping.erase(node->key); //That key goes out of cache
_mapping[key] = node; //New key gets in
node->data = data;
_attach(node); //Node goes to beginning
} else{
//GET THE NODE FROM THE BACK OF FREE LIST AND USE IT UP
//Get the entry from back of the free list
node = _freeEntries.back();
//Remove the node from the free list
_freeEntries.pop_back();
node[key] = data;
mapping[key] = node;
attach(node);
}
}
}
T void get(K key) {
LRUCacheEntry* node = mapping[key];
if (!node) {
return NULL;
}
detach(node);
attach(node);
return node->data;
}
//
// Purely doubly linked list functionality
//
void detach(LRUCacheEntry<K,T>* node)
{
//Remove a given node
node->prev->next = node->next;
node->next->prev = node->prev;
}
void attach(LRUCacheEntry<K,T>* node)
{
//Add node to the head of the doubly linked list
node->next = head->next;
node->prev = head;
head->next = node;
node->next->prev = node;
}
};