1#[macro_use]
9extern crate bitflags;
10
11use crate::token_ring::{Token, TokenRing};
12use std::borrow::Borrow;
13use std::collections::HashMap;
14use std::hash::Hash;
15use std::mem::MaybeUninit;
16
17bitflags! {
18 struct NodeType: u8 {
19 const EMPTY = 0b00001;
20 const HOT = 0b00010;
21 const COLD = 0b00100;
22 const TEST = 0b01000;
23 const MASK = Self::EMPTY.bits() | Self::HOT.bits() | Self::COLD.bits() | Self::TEST.bits();
24 const REFERENCE = 0b10000;
25 }
26}
27
28struct Node<K, V> {
29 key: MaybeUninit<K>,
30 value: Option<V>,
31 node_type: NodeType,
32}
33
34impl<K, V> Default for Node<K, V> {
35 fn default() -> Self {
36 Node {
37 key: MaybeUninit::uninit(),
38 value: None,
39 node_type: NodeType::EMPTY,
40 }
41 }
42}
43
44pub struct ClockProCache<K, V> {
46 capacity: usize,
47 test_capacity: usize,
48 cold_capacity: usize,
49 map: HashMap<K, Token>,
50 ring: TokenRing,
51 nodes: Vec<Node<K, V>>,
52 hand_hot: Token,
53 hand_cold: Token,
54 hand_test: Token,
55 count_hot: usize,
56 count_cold: usize,
57 count_test: usize,
58 inserted: u64,
59 evicted: u64,
60}
61
62impl<K, V> ClockProCache<K, V>
63where
64 K: Eq + Hash + Clone,
65{
66 pub fn new(capacity: usize) -> Result<Self, &'static str> {
68 Self::new_with_test_capacity(capacity, capacity)
69 }
70
71 pub fn new_with_test_capacity(
76 capacity: usize,
77 test_capacity: usize,
78 ) -> Result<Self, &'static str> {
79 if capacity < 3 {
80 return Err("Cache size cannot be less than 3 entries");
81 }
82 let mut nodes = Vec::with_capacity(capacity + test_capacity);
83 nodes.resize_with(capacity + test_capacity, Node::default);
84 let cache = ClockProCache {
85 capacity,
86 test_capacity,
87 cold_capacity: capacity,
88 map: HashMap::with_capacity(capacity + test_capacity),
89 ring: TokenRing::with_capacity(capacity + test_capacity),
90 nodes,
91 hand_hot: 0,
92 hand_cold: 0,
93 hand_test: 0,
94 count_hot: 0,
95 count_cold: 0,
96 count_test: 0,
97 inserted: 0,
98 evicted: 0,
99 };
100 Ok(cache)
101 }
102
103 #[inline]
105 pub fn len(&self) -> usize {
106 self.count_cold + self.count_hot
107 }
108
109 #[inline]
111 pub fn is_empty(&self) -> bool {
112 self.len() == 0
113 }
114
115 #[inline]
117 pub fn recent_len(&self) -> usize {
118 self.count_cold
119 }
120
121 #[inline]
123 pub fn frequent_len(&self) -> usize {
124 self.count_hot
125 }
126
127 #[inline]
129 pub fn test_len(&self) -> usize {
130 self.count_test
131 }
132
133 #[inline]
135 pub fn inserted(&self) -> u64 {
136 self.inserted
137 }
138
139 #[inline]
141 pub fn evicted(&self) -> u64 {
142 self.evicted
143 }
144
145 pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V>
149 where
150 K: Borrow<Q>,
151 Q: Eq + Hash,
152 {
153 let token = *self.map.get(key)?;
154 let node = &mut self.nodes[token];
155 let value = node.value.as_mut()?;
156 node.node_type.insert(NodeType::REFERENCE);
157 Some(value)
158 }
159
160 pub fn get<Q: ?Sized>(&mut self, key: &Q) -> Option<&V>
164 where
165 Q: Hash + Eq,
166 K: Borrow<Q>,
167 {
168 let token = *self.map.get(key)?;
169 let node = &mut self.nodes[token];
170 let value = &node.value.as_ref()?;
171 node.node_type.insert(NodeType::REFERENCE);
172 Some(value)
173 }
174
175 pub fn contains_key<Q: ?Sized>(&mut self, key: &Q) -> bool
177 where
178 Q: Hash + Eq,
179 K: Borrow<Q>,
180 {
181 if let Some(&token) = self.map.get(key) {
182 self.nodes[token].value.is_some()
183 } else {
184 false
185 }
186 }
187
188 pub fn insert(&mut self, key: K, value: V) -> bool {
193 let token = match self.map.get(&key).cloned() {
194 None => {
195 self.meta_add(key, value, NodeType::COLD);
196 self.count_cold += 1;
197 self.inserted += 1;
198 return true;
199 }
200 Some(token) => token,
201 };
202 {
203 let mentry = &mut self.nodes[token];
204 if mentry.value.is_some() {
205 mentry.value = Some(value);
206 mentry.node_type.insert(NodeType::REFERENCE);
207 return false;
208 }
209 }
210 if self.cold_capacity < self.capacity {
211 self.cold_capacity += 1;
212 }
213 self.count_test -= 1;
214 self.meta_del(token);
215 self.meta_add(key, value, NodeType::HOT);
216 self.count_hot += 1;
217 true
218 }
219
220 pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
225 where
226 K: Borrow<Q>,
227 Q: Eq + Hash,
228 {
229 let token = *self.map.get(key)?;
230 let node = &mut self.nodes[token];
231 let value = node.value.take();
232
233 if node.node_type.intersects(NodeType::HOT) {
235 self.count_hot -= 1;
236 } else if node.node_type.intersects(NodeType::COLD) {
237 self.count_cold -= 1;
238 }
239
240 self.meta_del(token);
241 value
242 }
243
244 fn meta_add(&mut self, key: K, value: V, node_type: NodeType) {
245 self.evict();
246 let token = self.ring.insert_after(self.hand_hot);
247 self.nodes[token] = Node {
248 key: MaybeUninit::new(key.clone()),
249 value: Some(value),
250 node_type,
251 };
252 self.map.insert(key, token);
253 if self.hand_cold == self.hand_hot {
254 self.hand_cold = self.ring.prev_for_token(self.hand_cold);
255 }
256 }
257
258 fn evict(&mut self) {
259 while self.count_hot + self.count_cold >= self.capacity {
260 self.run_hand_cold();
261 }
262 }
263
264 fn run_hand_cold(&mut self) {
265 let mut run_hand_test = false;
266 {
267 let mentry = &mut self.nodes[self.hand_cold];
268 if mentry.node_type.intersects(NodeType::COLD) {
269 if mentry.node_type.intersects(NodeType::REFERENCE) {
270 mentry.node_type = NodeType::HOT;
271 self.count_cold -= 1;
272 self.count_hot += 1;
273 } else {
274 mentry.node_type.remove(NodeType::MASK);
275 mentry.node_type.insert(NodeType::TEST);
276 mentry.value = None;
277 self.count_cold -= 1;
278 self.count_test += 1;
279 run_hand_test = true
280 }
281 }
282 }
283 if run_hand_test {
284 while self.count_test > self.test_capacity {
285 self.run_hand_test();
286 }
287 }
288 self.hand_cold = self.ring.next_for_token(self.hand_cold);
289 while self.count_hot > self.capacity - self.cold_capacity {
290 self.run_hand_hot();
291 }
292 }
293
294 fn run_hand_hot(&mut self) {
295 if self.hand_hot == self.hand_test {
296 self.run_hand_test();
297 }
298 {
299 let mentry = &mut self.nodes[self.hand_hot];
300 if mentry.node_type.intersects(NodeType::HOT) {
301 if mentry.node_type.intersects(NodeType::REFERENCE) {
302 mentry.node_type.remove(NodeType::REFERENCE);
303 } else {
304 mentry.node_type.remove(NodeType::MASK);
305 mentry.node_type.insert(NodeType::COLD);
306 self.count_hot -= 1;
307 self.count_cold += 1;
308 }
309 }
310 }
311 self.hand_hot = self.ring.next_for_token(self.hand_hot);
312 }
313
314 fn run_hand_test(&mut self) {
315 if self.hand_test == self.hand_cold {
316 self.run_hand_cold();
317 }
318 if self.nodes[self.hand_test]
319 .node_type
320 .intersects(NodeType::TEST)
321 {
322 let prev = self.ring.prev_for_token(self.hand_test);
323 let hand_test = self.hand_test;
324 self.meta_del(hand_test);
325 self.hand_test = prev;
326 self.count_test -= 1;
327 if self.cold_capacity > 1 {
328 self.cold_capacity -= 1;
329 }
330 }
331 self.hand_test = self.ring.next_for_token(self.hand_test);
332 }
333
334 fn meta_del(&mut self, token: Token) {
335 {
336 let mentry = &mut self.nodes[token];
337 mentry.node_type.remove(NodeType::MASK);
338 mentry.node_type.insert(NodeType::EMPTY);
339 mentry.value = None;
340 self.map.remove(unsafe { mentry.key.assume_init_ref() });
341 }
342 if token == self.hand_hot {
343 self.hand_hot = self.ring.prev_for_token(self.hand_hot);
344 }
345 if token == self.hand_cold {
346 self.hand_cold = self.ring.prev_for_token(self.hand_cold);
347 }
348 if token == self.hand_test {
349 self.hand_test = self.ring.prev_for_token(self.hand_test);
350 }
351 self.ring.remove(token);
352 self.evicted += 1;
353 }
354}
355
356unsafe impl<K, V> Send for ClockProCache<K, V>
357where
358 K: Send,
359 V: Send,
360{
361}
362
363unsafe impl<K, V> Sync for ClockProCache<K, V>
364where
365 K: Sync,
366 V: Sync,
367{
368}
369
370mod token_ring {
371 use slabigator::Slab;
372
373 pub type Token = usize;
374 const TOKEN_THUMBSTONE: Token = !0;
375
376 pub struct Node {
377 next: Token,
378 prev: Token,
379 }
380
381 pub struct TokenRing {
382 head: Token,
383 tail: Token,
384 slab: Slab<Node>,
385 }
386
387 impl TokenRing {
388 pub fn with_capacity(capacity: usize) -> Self {
389 if capacity < 1 {
390 panic!("A ring cannot have a capacity smaller than 1");
391 }
392 let slab = Slab::with_capacity(capacity).expect("requested capacity is too large");
393 TokenRing {
394 head: TOKEN_THUMBSTONE,
395 tail: TOKEN_THUMBSTONE,
396 slab,
397 }
398 }
399
400 #[allow(dead_code)]
401 #[inline]
402 pub fn len(&self) -> usize {
403 self.slab.len()
404 }
405
406 #[inline]
407 pub fn next_for_token(&self, token: Token) -> Token {
408 let next = self.slab[token].next;
409 if next == TOKEN_THUMBSTONE {
410 assert!(self.head != TOKEN_THUMBSTONE);
411 self.head
412 } else {
413 next
414 }
415 }
416
417 #[inline]
418 pub fn prev_for_token(&self, token: Token) -> Token {
419 let prev = self.slab[token].prev;
420 if prev == TOKEN_THUMBSTONE {
421 assert!(self.tail != TOKEN_THUMBSTONE);
422 self.tail
423 } else {
424 prev
425 }
426 }
427
428 pub fn remove(&mut self, token: Token) {
429 let (prev, next) = (self.slab[token].prev, self.slab[token].next);
430 if prev != TOKEN_THUMBSTONE {
431 self.slab[prev].next = next;
432 } else {
433 self.head = next;
434 }
435 if next != TOKEN_THUMBSTONE {
436 self.slab[next].prev = prev;
437 } else {
438 self.tail = prev;
439 }
440 self.slab[token].prev = TOKEN_THUMBSTONE;
441 self.slab[token].next = TOKEN_THUMBSTONE;
442 self.slab.remove(token).expect("removed token not in slab");
443 }
444
445 pub fn insert_after(&mut self, to: Token) -> Token {
446 if self.slab.is_empty() {
447 let node = Node {
448 prev: TOKEN_THUMBSTONE,
449 next: TOKEN_THUMBSTONE,
450 };
451 let token = self.slab.push_front(node).expect("over capacity");
452 self.head = token;
453 self.tail = token;
454 return token;
455 }
456 let to_prev = self.slab[to].prev;
457 let old_second = to_prev;
458 if old_second == TOKEN_THUMBSTONE {
459 let old_second = self.tail;
460 let node = Node {
461 prev: old_second,
462 next: TOKEN_THUMBSTONE,
463 };
464 let token = self.slab.push_front(node).expect("over capacity");
465 self.slab[old_second].next = token;
466 self.tail = token;
467 token
468 } else {
469 let node = Node {
470 prev: old_second,
471 next: to,
472 };
473 let token = self.slab.push_front(node).expect("over capacity");
474 self.slab[old_second].next = token;
475 self.slab[to].prev = token;
476 token
477 }
478 }
479 }
480}
481
482#[cfg(test)]
483mod tests {
484 use super::ClockProCache;
485
486 #[test]
487 fn test_cache() {
488 let mut cache = ClockProCache::new(3).unwrap();
489 cache.insert("testkey", "testvalue");
490 assert!(cache.contains_key("testkey"));
491 cache.insert("testkey2", "testvalue2");
492 assert!(cache.contains_key("testkey2"));
493 cache.insert("testkey3", "testvalue3");
494 assert!(cache.contains_key("testkey3"));
495 cache.insert("testkey4", "testvalue4");
496 assert!(cache.contains_key("testkey4"));
497 assert!(cache.contains_key("testkey3"));
498 assert!(!cache.contains_key("testkey2"));
499 cache.insert("testkey", "testvalue");
500 assert!(cache.get_mut("testkey").is_some());
501 assert!(cache.get_mut("testkey-nx").is_none());
502 }
503
504 #[test]
505 fn test_recycle() {
506 let mut cache: ClockProCache<u64, u64> = ClockProCache::new(3).unwrap();
507 for i in 0..7 {
508 assert!(cache.insert(i, i));
509 }
510 for i in 0..2 {
511 match cache.get(&i) {
512 None => {}
513 Some(x) => assert_eq!(*x, i),
514 }
515 }
516 }
517
518 #[test]
519 fn test_composite() {
520 let mut cache: ClockProCache<u64, (Vec<u8>, u64)> = ClockProCache::new(3).unwrap();
521 for i in 0..7 {
522 assert!(cache.insert(i, (vec![0u8; 12], i)));
523 }
524 for i in 0..2 {
525 match cache.get(&i) {
526 None => {}
527 Some(x) => assert_eq!(x.1, i),
528 }
529 }
530 }
531
532 #[test]
533 fn test_remove() {
534 let mut cache: ClockProCache<u64, u64> = ClockProCache::new(4).unwrap();
535 for i in 0..4 {
536 assert!(cache.insert(i, i));
537 }
538
539 assert_eq!(cache.remove(&2), Some(2));
540 assert_eq!(cache.remove(&3), Some(3));
541 assert_eq!(cache.remove(&3), None);
542
543 for i in 0..4 {
544 match i {
545 2 | 3 => assert_eq!(cache.get(&i), None),
546 _ => assert_eq!(*cache.get(&i).unwrap(), i),
547 };
548 }
549
550 for i in 2..4 {
552 assert!(cache.insert(i, i));
553 }
554
555 for i in 0..4 {
557 assert_eq!(*cache.get(&i).unwrap(), i);
558 }
559 }
560
561 #[test]
562 fn test_length_and_counters() {
563 let mut cache: ClockProCache<usize, usize> = ClockProCache::new(5).unwrap();
564
565 assert_eq!(cache.is_empty(), true);
567
568 for i in 1..=5 {
569 assert!(cache.insert(i, i));
571 assert_eq!(cache.len(), i);
572 }
573
574 assert_eq!(cache.is_empty(), false);
576 assert_eq!(cache.inserted(), 5);
577 assert_eq!(cache.frequent_len(), 0);
578 assert_eq!(cache.recent_len(), 5);
579
580 assert!(cache.insert(6, 6));
582 assert!(cache.insert(7, 7));
583
584 assert_eq!(cache.len(), 5);
585 assert_eq!(cache.inserted(), 7);
586 assert_eq!(cache.frequent_len(), 0);
587 assert_eq!(cache.recent_len(), 5);
588
589 assert_eq!(cache.get(&6), Some(&6));
592 assert_eq!(cache.get(&7), Some(&7));
593
594 for i in 8..=15 {
595 assert!(cache.insert(i, i));
596 }
597
598 assert_eq!(cache.get(&6), Some(&6));
600 assert_eq!(cache.get(&7), Some(&7));
601
602 assert_eq!(cache.len(), 5);
603 assert_eq!(cache.inserted(), 15);
604 assert_eq!(cache.frequent_len(), 2);
605 assert_eq!(cache.recent_len(), 3);
606 assert_eq!(cache.test_len(), 5);
607
608 assert_eq!(cache.remove(&6), Some(6));
610 assert_eq!(cache.remove(&15), Some(15));
611 assert_eq!(cache.frequent_len(), 1);
612 assert_eq!(cache.recent_len(), 2);
613 }
614
615 #[test]
616 fn test_evicted_to_hot() {
617 let mut cache: ClockProCache<usize, usize> =
618 ClockProCache::new_with_test_capacity(3, 30).unwrap();
619
620 for i in 0..30 {
622 assert!(cache.insert(i, i));
623 }
624
625 assert_eq!(cache.frequent_len(), 0);
626 assert_eq!(cache.recent_len(), 3);
627 assert_eq!(cache.test_len(), 27);
628
629 assert_eq!(cache.get(&10), None);
631
632 assert!(cache.insert(10, 10));
634 assert_eq!(cache.frequent_len(), 1);
635 assert_eq!(cache.recent_len(), 2);
636 assert_eq!(cache.test_len(), 27);
637 }
638}