async_map/
lockingmap.rs

1use std::collections::HashMap;
2use std::future::Future;
3use std::hash::Hash;
4use std::pin::Pin;
5use std::sync::{Arc, RwLock};
6
7use crate::{AsyncKey, AsyncMap, AsyncStorable, FactoryBorrow};
8
9#[derive(Clone)]
10pub struct LockingMap<K, V>
11where
12    K: 'static + Clone + Hash + Eq + Send + Unpin,
13    V: 'static + Clone + Send + Unpin,
14{
15    map: Arc<RwLock<HashMap<K, V>>>,
16}
17
18impl<K: AsyncKey + Sync, V: AsyncStorable + Sync> AsyncMap for LockingMap<K, V> {
19    type Key = K;
20    type Value = V;
21
22    fn get_if_present(&self, key: &Self::Key) -> Option<Self::Value> {
23        match self.map.read() {
24            Ok(read_guard) => read_guard.get(key).map(Self::Value::clone),
25            Err(_) => {
26                panic!("Can't deal with this yet")
27            }
28        }
29    }
30
31    fn get<'a, 'b, B: FactoryBorrow<K, V>>(
32        &self,
33        key: &'a Self::Key,
34        factory: B,
35    ) -> Pin<Box<dyn Future<Output = Self::Value> + Send + 'b>> {
36        let map = self.map.clone();
37        let key = key.clone();
38        Box::pin(async move {
39            match map.read() {
40                Ok(read_guard) => match read_guard.get(&key) {
41                    Some(value_ref) => value_ref.clone(),
42                    None => {
43                        drop(read_guard);
44                        LockingMap::create_if_necessary(&map, key, factory)
45                    }
46                },
47                Err(_) => {
48                    panic!("Can't deal with this yet");
49                }
50            }
51        })
52    }
53}
54
55impl<K, V> LockingMap<K, V>
56where
57    K: AsyncKey,
58    V: AsyncStorable,
59{
60    pub fn new() -> Self {
61        LockingMap {
62            map: Arc::default(),
63        }
64    }
65
66    fn create_if_necessary<'a, B: FactoryBorrow<K, V>>(
67        map: &'a Arc<RwLock<HashMap<K, V>>>,
68        key: K,
69        factory: B,
70    ) -> V {
71        match map.write() {
72            Ok(mut map) => match map.get(&key) {
73                Some(value_ref) => value_ref.clone(),
74                None => {
75                    let value = factory.borrow()(&key);
76                    map.insert(key, value.clone());
77                    value
78                }
79            },
80            Err(_) => {
81                todo!()
82            }
83        }
84    }
85}