qwreey_utility_rs/
hashmap.rs

1use std::{
2    any::{Any, TypeId},
3    cell::UnsafeCell,
4    collections::HashMap,
5    hash::Hash,
6    marker::PhantomData,
7    ops::{Deref, DerefMut},
8    sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
9};
10
11struct MapField<T> {
12    data: T,
13    lock: RwLock<()>,
14}
15impl<T> MapField<T> {
16    fn new(data: T) -> Self {
17        Self {
18            data,
19            lock: RwLock::new(()),
20        }
21    }
22}
23
24pub struct RwHashMap<Key: Hash + Eq> {
25    #[allow(clippy::type_complexity)]
26    table: UnsafeCell<HashMap<Key, MapField<Box<UnsafeCell<dyn Any + Send>>>>>,
27    table_rw: RwLock<()>,
28}
29unsafe impl<T: Hash + Eq> Send for RwHashMap<T> {}
30unsafe impl<T: Hash + Eq> Sync for RwHashMap<T> {}
31impl<Key: Hash + Eq> RwHashMap<Key> {
32    #[allow(clippy::new_without_default)]
33    pub fn new() -> Self {
34        Self {
35            table: UnsafeCell::new(HashMap::new()),
36            table_rw: RwLock::new(()),
37        }
38    }
39    pub fn get<T: 'static + Any + Send>(&'_ self, key: &Key) -> Option<MapReader<'_, T>> {
40        let field = unsafe { self.table.get().as_ref().unwrap() }.get(key)?;
41
42        Some(MapReader::<T>::new(
43            self.table_rw.read().ok()?,
44            field.lock.read().ok()?,
45            unsafe { field.data.get().as_ref().unwrap() },
46        ))
47    }
48    pub fn get_mut<T: 'static + Any + Send>(&'_ self, key: &Key) -> Option<MapWriter<'_, T>> {
49        let field = unsafe { self.table.get().as_ref().unwrap() }.get(key)?;
50
51        Some(MapWriter::<T>::new(
52            self.table_rw.read().ok()?,
53            field.lock.write().ok()?,
54            unsafe { field.data.get().as_mut().unwrap() },
55        ))
56    }
57    pub fn insert<T: 'static + Any + Send>(&self, key: Key, value: T) -> Option<()> {
58        let lock = self.table_rw.write().ok()?;
59        unsafe { self.table.get().as_mut().unwrap() }
60            .insert(key, MapField::new(Box::new(UnsafeCell::new(value))));
61        drop(lock);
62        Some(())
63    }
64    /// # Safety
65    /// This function does not lock the table or the field, so it is up to the caller to ensure
66    /// that no other threads are accessing the table or the field while this function is being
67    /// called.
68    #[allow(clippy::mut_from_ref)]
69    pub unsafe fn get_mut_nonlock<T: 'static + Any + Send>(
70        &'_ self,
71        key: &Key,
72    ) -> Option<&'_ mut T> {
73        let field = unsafe { self.table.get().as_ref().unwrap() }.get(key)?;
74
75        field.data.get().as_mut().unwrap().downcast_mut::<T>()
76    }
77}
78
79pub struct RwTypedMap(RwHashMap<TypeId>);
80unsafe impl Send for RwTypedMap {}
81unsafe impl Sync for RwTypedMap {}
82impl RwTypedMap {
83    #[allow(clippy::new_without_default)]
84    pub fn new() -> Self {
85        Self(RwHashMap::new())
86    }
87    #[inline]
88    pub fn get_of<T: 'static + Send>(&'_ self) -> Option<MapReader<'_, T>> {
89        self.0.get(&TypeId::of::<T>())
90    }
91    #[inline]
92    pub fn get_of_mut<T: 'static + Send>(&'_ self) -> Option<MapWriter<'_, T>> {
93        self.0.get_mut(&TypeId::of::<T>())
94    }
95    /// # Safety
96    /// This function does not lock the table or the field, so it is up to the caller to ensure
97    /// that no other threads are accessing the table or the field while this function is being
98    /// called.
99    #[allow(clippy::mut_from_ref)]
100    #[inline]
101    pub unsafe fn get_of_mut_nonlock<T: 'static + Send>(&'_ self) -> Option<&'_ mut T> {
102        self.0.get_mut_nonlock(&TypeId::of::<T>())
103    }
104    #[inline]
105    pub fn insert_of<T: 'static + Send>(&self, value: T) {
106        self.0.insert(TypeId::of::<T>(), value);
107    }
108}
109
110pub struct RwMap {
111    named: RwHashMap<String>,
112    typed: RwTypedMap,
113}
114unsafe impl Send for RwMap {}
115unsafe impl Sync for RwMap {}
116impl RwMap {
117    #[allow(clippy::new_without_default)]
118    pub fn new() -> Self {
119        Self {
120            named: RwHashMap::<String>::new(),
121            typed: RwTypedMap::new(),
122        }
123    }
124    #[inline]
125    pub fn get_of<T: 'static + Send + Sync>(&'_ self) -> Option<MapReader<'_, T>> {
126        self.typed.get_of::<T>()
127    }
128    #[inline]
129    pub fn get_of_mut<T: 'static + Send + Sync>(&'_ self) -> Option<MapWriter<'_, T>> {
130        self.typed.get_of_mut::<T>()
131    }
132    /// # Safety
133    /// This function does not lock the table or the field, so it is up to the caller to ensure
134    /// that no other threads are accessing the table or the field while this function is being
135    /// called.
136    #[allow(clippy::mut_from_ref)]
137    #[inline]
138    pub unsafe fn get_of_mut_nonlock<T: 'static + Send>(&'_ self) -> Option<&'_ mut T> {
139        self.typed.get_of_mut_nonlock::<T>()
140    }
141    #[inline]
142    pub fn insert_of<T: 'static + Send + Sync>(&self, value: T) {
143        self.typed.insert_of::<T>(value);
144    }
145    #[inline]
146    pub fn get<T: 'static + Send + Sync>(
147        &'_ self,
148        key: impl Into<String>,
149    ) -> Option<MapReader<'_, T>> {
150        self.named.get::<T>(&key.into())
151    }
152    #[inline]
153    pub fn get_mut<T: 'static + Send + Sync>(
154        &'_ self,
155        key: impl Into<String>,
156    ) -> Option<MapWriter<'_, T>> {
157        self.named.get_mut::<T>(&key.into())
158    }
159    /// # Safety
160    /// This function does not lock the table or the field, so it is up to the caller to ensure
161    /// that no other threads are accessing the table or the field while this function is being
162    /// called.
163    #[allow(clippy::mut_from_ref)]
164    #[inline]
165    pub unsafe fn get_mut_nonlock<T: 'static + Send + Sync>(
166        &'_ self,
167        key: impl Into<String>,
168    ) -> Option<&'_ mut T> {
169        self.named.get_mut_nonlock::<T>(&key.into())
170    }
171    #[inline]
172    pub fn insert<T: 'static + Send + Sync>(&self, key: impl Into<String>, value: T) {
173        self.named.insert(key.into(), value);
174    }
175}
176
177pub struct MapReader<'a, T> {
178    data: &'a T,
179    _table_lock: RwLockReadGuard<'a, ()>,
180    _field_lock: RwLockReadGuard<'a, ()>,
181    _p: PhantomData<T>,
182}
183unsafe impl<'a, T> Send for MapReader<'a, T> {}
184impl<'a, T: 'static> Deref for MapReader<'a, T> {
185    type Target = T;
186    fn deref(&self) -> &Self::Target {
187        self.data
188    }
189}
190impl<'a, T: 'static> MapReader<'a, T> {
191    fn new(
192        table_lock: RwLockReadGuard<'a, ()>,
193        field_lock: RwLockReadGuard<'a, ()>,
194        data: &'a (dyn Any + Send),
195    ) -> Self {
196        Self {
197            data: data.downcast_ref::<T>().unwrap(),
198            _field_lock: field_lock,
199            _table_lock: table_lock,
200            _p: PhantomData,
201        }
202    }
203}
204
205pub struct MapWriter<'a, T> {
206    data: &'a mut T,
207    _table_lock: RwLockReadGuard<'a, ()>,
208    _field_lock: RwLockWriteGuard<'a, ()>,
209    _p: PhantomData<T>,
210}
211unsafe impl<'a, T> Send for MapWriter<'a, T> {}
212impl<'a, T: 'static> Deref for MapWriter<'a, T> {
213    type Target = T;
214    fn deref(&self) -> &Self::Target {
215        self.data
216    }
217}
218impl<'a, T: 'static> DerefMut for MapWriter<'a, T> {
219    fn deref_mut(&mut self) -> &mut Self::Target {
220        self.data
221    }
222}
223impl<'a, T: 'static> MapWriter<'a, T> {
224    fn new(
225        table_lock: RwLockReadGuard<'a, ()>,
226        field_lock: RwLockWriteGuard<'a, ()>,
227        data: &'a mut (dyn Any + Send),
228    ) -> Self {
229        Self {
230            data: data.downcast_mut::<T>().unwrap(),
231            _field_lock: field_lock,
232            _table_lock: table_lock,
233            _p: PhantomData,
234        }
235    }
236}
237
238#[derive(Clone)]
239pub struct ArcRwMap(Arc<RwMap>);
240unsafe impl Send for ArcRwMap {}
241impl Deref for ArcRwMap {
242    type Target = RwMap;
243    fn deref(&self) -> &Self::Target {
244        &self.0
245    }
246}
247impl DerefMut for ArcRwMap {
248    fn deref_mut(&mut self) -> &mut Self::Target {
249        Arc::get_mut(&mut self.0).unwrap()
250    }
251}
252impl ArcRwMap {
253    #[allow(clippy::new_without_default)]
254    pub fn new() -> Self {
255        Self(Arc::new(RwMap::new()))
256    }
257}
258
259#[macro_export]
260macro_rules! write_map {
261    ($map:expr, { $($key:expr => $val:expr),* $(,)? }) => {
262        {
263            #[allow(non_snake_case)]
264            let mut WRITE_MAP_HANDLE = $map;
265
266            $(WRITE_MAP_HANDLE.insert($key, $val);)*;
267
268            WRITE_MAP_HANDLE
269        }
270    };
271}