1use crate::hashing::HashMap;
2use std::hash::Hash;
3
4#[derive(Copy, Clone)]
5struct LruCacheNode {
6 next: u32,
7 previous: u32,
8}
9
10pub struct LruCache<K, V> {
11 lru_list_head: u32,
13 lru_list_tail: u32,
14 lru_list: Vec<LruCacheNode>,
15
16 lru_list_pairs: Vec<Option<(K, V)>>,
18
19 lookup: HashMap<K, u32>,
21}
22
23impl<K: Clone + PartialEq + Eq + Hash, V> LruCache<K, V> {
24 pub fn new(size: u32) -> LruCache<K, V> {
25 assert!(size > 2);
26 let mut lru_list = vec![
27 LruCacheNode {
28 next: 0,
29 previous: 0
30 };
31 size as usize
32 ];
33 lru_list[0].previous = u32::MAX;
34 lru_list[0].next = 1;
35 for i in 1..(size - 1) {
36 lru_list[i as usize].previous = i - 1;
37 lru_list[i as usize].next = i + 1;
38 }
39 lru_list[size as usize - 1].previous = size - 2;
40 lru_list[size as usize - 1].next = u32::MAX;
41
42 let mut lru_list_pairs = Vec::with_capacity(size as usize);
43 for _ in 0..size {
44 lru_list_pairs.push(None);
45 }
46
47 let lookup = HashMap::default();
48
49 LruCache {
50 lru_list_head: 0,
51 lru_list_tail: size - 1,
52 lru_list,
53 lru_list_pairs,
54 lookup,
55 }
56 }
57
58 pub fn pairs(&self) -> &Vec<Option<(K, V)>> {
75 &self.lru_list_pairs
76 }
77
78 pub fn pairs_mut(&mut self) -> &mut Vec<Option<(K, V)>> {
79 &mut self.lru_list_pairs
80 }
81
82 fn move_to_front(
83 &mut self,
84 node_index: u32,
85 ) {
86 let node = self.lru_list[node_index as usize];
88
89 if node_index == self.lru_list_head {
90 assert_eq!(node.previous, u32::MAX);
92 assert_ne!(node.next, u32::MAX);
93 return;
94 }
95
96 if node_index == self.lru_list_tail {
97 assert_eq!(node.next, u32::MAX);
99 assert_ne!(node.previous, u32::MAX);
100 self.lru_list_tail = node.previous;
101 }
102
103 assert_ne!(node.previous, u32::MAX);
105 self.lru_list[node.previous as usize].next = node.next;
106 if node.next != u32::MAX {
107 self.lru_list[node.next as usize].previous = node.previous;
108 }
109
110 assert_eq!(
112 self.lru_list[self.lru_list_head as usize].previous,
113 u32::MAX
114 );
115 self.lru_list[self.lru_list_head as usize].previous = node_index;
116 self.lru_list[node_index as usize].previous = u32::MAX;
117 self.lru_list[node_index as usize].next = self.lru_list_head;
118 self.lru_list_head = node_index;
119
120 }
122
123 fn move_to_back(
124 &mut self,
125 node_index: u32,
126 ) {
127 let node = self.lru_list[node_index as usize];
129
130 if node_index == self.lru_list_tail {
131 assert_eq!(node.next, u32::MAX);
133 assert_ne!(node.previous, u32::MAX);
134 return;
135 }
136
137 if node_index == self.lru_list_head {
138 assert_eq!(node.previous, u32::MAX);
140 assert_ne!(node.next, u32::MAX);
141 self.lru_list_head = node.next;
142 }
143
144 if node.previous != u32::MAX {
146 self.lru_list[node.previous as usize].next = node.next;
147 }
148 assert_ne!(node.next, u32::MAX);
149 self.lru_list[node.next as usize].previous = node.previous;
150
151 assert_eq!(self.lru_list[self.lru_list_tail as usize].next, u32::MAX);
153 self.lru_list[self.lru_list_tail as usize].next = node_index;
154 self.lru_list[node_index as usize].previous = self.lru_list_tail;
155 self.lru_list[node_index as usize].next = u32::MAX;
156 self.lru_list_tail = node_index;
157
158 }
160
161 pub fn get(
162 &mut self,
163 k: &K,
164 mark_as_recently_used: bool,
165 ) -> Option<&V> {
166 if let Some(&node_index) = self.lookup.get(k) {
167 if mark_as_recently_used {
168 self.move_to_front(node_index);
170 }
171 self.lru_list_pairs[node_index as usize]
173 .as_ref()
174 .map(|(_, v)| v)
175 } else {
176 None
177 }
178 }
179
180 pub fn get_mut(
181 &mut self,
182 k: &K,
183 mark_as_recently_used: bool,
184 ) -> Option<&mut V> {
185 if let Some(&node_index) = self.lookup.get(k) {
186 if mark_as_recently_used {
187 self.move_to_front(node_index);
189 }
190 self.lru_list_pairs[node_index as usize]
192 .as_mut()
193 .map(|(_, v)| v)
194 } else {
195 None
196 }
197 }
198
199 pub fn insert(
200 &mut self,
201 k: K,
202 v: V,
203 ) {
204 if let Some(key_to_remove) = self.lru_list_pairs[self.lru_list_tail as usize]
205 .as_ref()
206 .map(|(k, _)| k)
207 .cloned()
208 {
209 self.remove(&key_to_remove);
210 }
211
212 let node_index = self.lru_list_tail;
214 if let Some((k, _)) = &self.lru_list_pairs[node_index as usize] {
215 self.lookup.remove(k);
216 }
217
218 self.move_to_front(self.lru_list_tail);
219 self.lookup.insert(k.clone(), node_index);
220 self.lru_list_pairs[node_index as usize] = Some((k, v));
221 }
222
223 pub fn remove(
224 &mut self,
225 k: &K,
226 ) -> Option<V> {
227 if let Some(&node_index) = self.lookup.get(k) {
228 self.move_to_back(node_index);
230 let v = self.lru_list_pairs[node_index as usize]
232 .take()
233 .map(|(_, v)| v);
234 self.lookup.remove(k);
235 v
236 } else {
237 None
238 }
239 }
240}
241
242#[cfg(test)]
243mod test {
244 use super::*;
245
246 #[test]
247 fn check_lru_gets_full() {
248 let mut lru_cache = LruCache::new(3);
249 lru_cache.insert(0, 0);
250 lru_cache.insert(1, 1);
251 lru_cache.insert(2, 2);
252
253 assert!(lru_cache.get(&0, false).is_some());
255 assert!(lru_cache.get(&1, false).is_some());
256 assert!(lru_cache.get(&2, false).is_some());
257
258 lru_cache.insert(3, 3);
260 assert!(lru_cache.get(&0, false).is_none());
261 assert!(lru_cache.get(&1, false).is_some());
262 assert!(lru_cache.get(&2, false).is_some());
263 assert!(lru_cache.get(&3, false).is_some());
264 }
265
266 #[test]
267 fn check_lru_deletes_least_recently_used() {
268 let mut lru_cache = LruCache::new(3);
269 lru_cache.insert(0, 0);
270 lru_cache.insert(1, 1);
271 lru_cache.insert(2, 2);
272
273 assert!(lru_cache.get(&0, false).is_some());
275 assert!(lru_cache.get(&1, false).is_some());
276 assert!(lru_cache.get(&2, false).is_some());
277
278 lru_cache.get(&0, true);
280
281 lru_cache.insert(3, 3);
282 assert!(lru_cache.get(&0, false).is_some());
283 assert!(lru_cache.get(&1, false).is_none());
284 assert!(lru_cache.get(&2, false).is_some());
285 assert!(lru_cache.get(&3, false).is_some());
286 }
287
288 #[test]
289 fn check_remove() {
290 let mut lru_cache = LruCache::new(3);
291 lru_cache.insert(0, 0);
292 lru_cache.insert(1, 1);
293 lru_cache.insert(2, 2);
294
295 assert!(lru_cache.get(&0, false).is_some());
297 assert!(lru_cache.get(&1, false).is_some());
298 assert!(lru_cache.get(&2, false).is_some());
299
300 lru_cache.remove(&0);
301 lru_cache.remove(&2);
302 lru_cache.remove(&1);
303
304 lru_cache.insert(3, 3);
305 assert!(lru_cache.get(&0, false).is_none());
306 assert!(lru_cache.get(&1, false).is_none());
307 assert!(lru_cache.get(&2, false).is_none());
308 assert!(lru_cache.get(&3, false).is_some());
309 }
310}