1use lru::LruCache;
2use std::convert::Infallible;
3use std::hash::Hash;
4use std::sync::Mutex;
5
6pub struct SyncLruCache<K, V> {
9 inner: Mutex<LruCache<K, V>>,
10}
11
12impl<K, V> SyncLruCache<K, V>
13where
14 K: Hash + Eq,
15 V: Clone,
16{
17 pub fn new(cap: usize) -> Self {
19 Self { inner: Mutex::new(LruCache::<K, V>::new(cap)) }
20 }
21
22 pub fn len(&self) -> usize {
24 self.inner.lock().unwrap().len()
25 }
26
27 pub fn is_empty(&self) -> bool {
29 self.inner.lock().unwrap().is_empty()
30 }
31
32 pub fn get_or_put<F>(&self, key: K, f: F) -> V
36 where
37 V: Clone,
38 F: FnOnce(&K) -> V,
39 {
40 Result::<_, Infallible>::unwrap(self.get_or_try_put(key, |k| Ok(f(k))))
41 }
42
43 pub fn get_or_try_put<F, E>(&self, key: K, f: F) -> Result<V, E>
52 where
53 V: Clone,
54 F: FnOnce(&K) -> Result<V, E>,
55 {
56 if let Some(result) = self.get(&key) {
57 return Ok(result);
58 }
59 let val = f(&key)?;
60 let val_clone = val.clone();
61 self.inner.lock().unwrap().put(key, val_clone);
62 Ok(val)
63 }
64
65 pub fn put(&self, key: K, value: V) {
68 self.inner.lock().unwrap().put(key, value);
69 }
70
71 pub fn get(&self, key: &K) -> Option<V> {
74 self.inner.lock().unwrap().get(key).cloned()
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn test_cache() {
84 let cache = SyncLruCache::<u64, Vec<u64>>::new(100);
85
86 assert_eq!(cache.get(&0u64), None);
87 assert_eq!(cache.get_or_put(123u64, |key| vec![*key, 123]), vec![123u64, 123]);
88 assert_eq!(cache.get(&123u64), Some(vec![123u64, 123]));
89 assert_eq!(cache.get(&0u64), None);
90 }
91}