Skip to main content

miden_node_utils/
lru_cache.rs

1use std::hash::Hash;
2use std::num::NonZeroUsize;
3use std::sync::{Arc, Mutex, MutexGuard};
4
5use lru::LruCache as InnerCache;
6use tracing::instrument;
7
8/// A newtype wrapper around an LRU cache. Ensures that the cache lock is not held across
9/// await points.
10#[derive(Clone)]
11pub struct LruCache<K, V>(Arc<Mutex<InnerCache<K, V>>>);
12
13impl<K, V> LruCache<K, V>
14where
15    K: Hash + Eq,
16    V: Clone,
17{
18    /// Creates a new cache with the given capacity.
19    pub fn new(capacity: NonZeroUsize) -> Self {
20        Self(Arc::new(Mutex::new(InnerCache::new(capacity))))
21    }
22
23    /// Retrieves a value from the cache.
24    pub fn get(&self, key: &K) -> Option<V> {
25        self.lock().get(key).cloned()
26    }
27
28    /// Puts a value into the cache.
29    pub fn put(&self, key: K, value: V) {
30        self.lock().put(key, value);
31    }
32
33    #[instrument(name = "lru.lock", skip_all)]
34    fn lock(&self) -> MutexGuard<'_, InnerCache<K, V>> {
35        // SAFETY: The mutex is only held for the duration of the get/put operation
36        // where panics are possible only if we're running out of memory, in which
37        // case the entire process is likely to be unstable anyway.
38        self.0.lock().expect("LRU cache mutex poisoned")
39    }
40}