Skip to main content

poly_commitment/
hash_map_cache.rs

1use std::{
2    cmp::Eq,
3    collections::HashMap,
4    hash::Hash,
5    ops::Deref,
6    sync::{Arc, Mutex},
7};
8
9#[derive(Debug, Clone, Default)]
10pub struct HashMapCache<Key: Hash, Value> {
11    contents: Arc<Mutex<HashMap<Key, Arc<Value>>>>,
12}
13
14impl<Key: Hash + Eq, Value> HashMapCache<Key, Value> {
15    #[must_use]
16    pub fn new() -> Self {
17        Self {
18            contents: Arc::new(Mutex::new(HashMap::new())),
19        }
20    }
21
22    #[must_use]
23    pub(crate) fn new_from_hashmap(hashmap: HashMap<Key, Arc<Value>>) -> Self {
24        Self {
25            contents: Arc::new(Mutex::new(hashmap)),
26        }
27    }
28
29    /// Sets a value by key only if it hasn't already been set
30    ///
31    /// # Panics
32    ///
33    /// Panics if the internal mutex is poisoned.
34    pub fn set_once(&self, key: Key, value: Value) {
35        let mut hashmap = self.contents.lock().unwrap();
36        let _ = hashmap.entry(key).or_insert_with(|| Arc::new(value));
37    }
38
39    /// Retrieves a cached value by key, or generates and caches it using the
40    /// provided closure.
41    ///
42    /// # Panics
43    ///
44    /// Panics if the internal mutex is poisoned.
45    #[allow(clippy::significant_drop_tightening)] // it's a false positive, you can't drop the lock any earlier
46    pub(crate) fn get_or_generate<F: FnOnce() -> Value>(
47        &self,
48        key: Key,
49        generator: F,
50    ) -> impl Deref<Target = Value> + '_ {
51        let mut hashmap = self.contents.lock().unwrap();
52        let entry = hashmap.entry(key).or_insert_with(|| Arc::new(generator()));
53        Arc::clone(entry)
54    }
55
56    /// Returns `true` if the cache contains the given key.
57    ///
58    /// # Panics
59    ///
60    /// Panics if the internal mutex is poisoned.
61    pub fn contains_key(&self, key: &Key) -> bool {
62        self.contents.lock().unwrap().contains_key(key)
63    }
64}
65
66#[allow(clippy::implicit_hasher)]
67#[allow(clippy::fallible_impl_from)]
68impl<Key: Hash + Eq + Clone, Value: Clone> From<HashMapCache<Key, Value>>
69    for HashMap<Key, Arc<Value>>
70{
71    fn from(cache: HashMapCache<Key, Value>) -> Self {
72        cache.contents.lock().unwrap().clone()
73    }
74}