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}