|
1 | 1 | use crate::rwlock::{Locks, MutexGuardWrapper}; |
2 | 2 | use once_cell::sync::OnceCell; |
3 | | -use scc::{hash_map::Entry, HashMap}; |
| 3 | +use std::collections::HashMap; |
4 | 4 | use std::sync::atomic::AtomicU32; |
| 5 | +use std::sync::Mutex; |
| 6 | + |
| 7 | +pub(crate) struct ValueRef(UniqueReentrantMutex); |
| 8 | + |
| 9 | +impl ValueRef { |
| 10 | + pub fn get(&self) -> &UniqueReentrantMutex { |
| 11 | + &self.0 |
| 12 | + } |
| 13 | +} |
| 14 | + |
| 15 | +pub(crate) struct LockMap { |
| 16 | + inner: Mutex<HashMap<String, UniqueReentrantMutex>>, |
| 17 | +} |
| 18 | + |
| 19 | +impl LockMap { |
| 20 | + fn new() -> Self { |
| 21 | + LockMap { |
| 22 | + inner: Mutex::new(HashMap::new()), |
| 23 | + } |
| 24 | + } |
| 25 | + |
| 26 | + pub fn get(&self, key: &str) -> Option<ValueRef> { |
| 27 | + self.inner.lock().unwrap().get(key).cloned().map(ValueRef) |
| 28 | + } |
| 29 | + |
| 30 | + pub fn contains(&self, key: &str) -> bool { |
| 31 | + self.inner.lock().unwrap().contains_key(key) |
| 32 | + } |
| 33 | + |
| 34 | + fn get_or_insert( |
| 35 | + &self, |
| 36 | + key: &str, |
| 37 | + f: impl FnOnce() -> UniqueReentrantMutex, |
| 38 | + ) -> UniqueReentrantMutex { |
| 39 | + let mut map = self.inner.lock().unwrap(); |
| 40 | + map.entry(key.to_owned()).or_insert_with(f).clone() |
| 41 | + } |
| 42 | +} |
5 | 43 |
|
6 | 44 | #[derive(Clone)] |
7 | 45 | pub(crate) struct UniqueReentrantMutex { |
@@ -41,11 +79,11 @@ impl UniqueReentrantMutex { |
41 | 79 | } |
42 | 80 |
|
43 | 81 | #[inline] |
44 | | -pub(crate) fn global_locks() -> &'static HashMap<String, UniqueReentrantMutex> { |
| 82 | +pub(crate) fn global_locks() -> &'static LockMap { |
45 | 83 | #[cfg(feature = "test_logging")] |
46 | 84 | let _ = env_logger::builder().try_init(); |
47 | | - static LOCKS: OnceCell<HashMap<String, UniqueReentrantMutex>> = OnceCell::new(); |
48 | | - LOCKS.get_or_init(HashMap::new) |
| 85 | + static LOCKS: OnceCell<LockMap> = OnceCell::new(); |
| 86 | + LOCKS.get_or_init(LockMap::new) |
49 | 87 | } |
50 | 88 |
|
51 | 89 | /// Check if the current thread is holding a serial lock |
@@ -123,11 +161,7 @@ pub(crate) fn check_new_key(name: &str) { |
123 | 161 | }; |
124 | 162 |
|
125 | 163 | // This is the rare path, which avoids the multi-writer situation mostly |
126 | | - let entry = global_locks().entry(name.to_owned()); |
127 | | - match entry { |
128 | | - Entry::Occupied(o) => o, |
129 | | - Entry::Vacant(v) => v.insert_entry(UniqueReentrantMutex::new_mutex(name)), |
130 | | - }; |
| 164 | + global_locks().get_or_insert(name, || UniqueReentrantMutex::new_mutex(name)); |
131 | 165 | } |
132 | 166 |
|
133 | 167 | #[cfg(test)] |
|
0 commit comments