1use lru::LruCache;
2use parking_lot::{Mutex, MutexGuard};
3use std::convert::Infallible;
4use std::hash::Hash;
5use std::num::NonZeroUsize;
6
7pub struct SyncLruCache<K, V> {
10 inner: Mutex<LruCache<K, V>>,
11}
12
13impl<K, V> SyncLruCache<K, V>
14where
15 K: Hash + Eq,
16 V: Clone,
17{
18 pub fn new(cap: usize) -> Self {
20 Self { inner: Mutex::new(LruCache::<K, V>::new(NonZeroUsize::new(cap).unwrap())) }
21 }
22
23 pub fn len(&self) -> usize {
25 self.inner.lock().len()
26 }
27
28 pub fn is_empty(&self) -> bool {
30 self.inner.lock().is_empty()
31 }
32
33 pub fn contains(&self, key: &K) -> bool {
35 self.inner.lock().contains(key)
36 }
37
38 pub fn push(&self, key: K, value: V) -> Option<(K, V)> {
42 self.inner.lock().push(key, value)
43 }
44
45 pub fn get_or_put<F>(&self, key: K, f: F) -> V
49 where
50 V: Clone,
51 F: FnOnce(&K) -> V,
52 {
53 Result::<_, Infallible>::unwrap(self.get_or_try_put(key, |k| Ok(f(k))))
54 }
55
56 pub fn get_or_try_put<F, E>(&self, key: K, f: F) -> Result<V, E>
65 where
66 V: Clone,
67 F: FnOnce(&K) -> Result<V, E>,
68 {
69 if let Some(result) = self.get(&key) {
70 return Ok(result);
71 }
72 let val = f(&key)?;
73 let val_clone = val.clone();
74 self.inner.lock().put(key, val_clone);
75 Ok(val)
76 }
77
78 pub fn put(&self, key: K, value: V) {
81 self.inner.lock().put(key, value);
82 }
83
84 pub fn get(&self, key: &K) -> Option<V> {
87 self.inner.lock().get(key).cloned()
88 }
89
90 pub fn lock(&self) -> MutexGuard<LruCache<K, V>> {
92 self.inner.lock()
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn test_cache() {
102 let cache = SyncLruCache::<u64, Vec<u64>>::new(100);
103
104 assert_eq!(cache.get(&0u64), None);
105 assert_eq!(cache.get_or_put(123u64, |key| vec![*key, 123]), vec![123u64, 123]);
106 assert_eq!(cache.get(&123u64), Some(vec![123u64, 123]));
107 assert_eq!(cache.get(&0u64), None);
108 }
109}