|
1 | 1 | use crate::rwlock::{Locks, MutexGuardWrapper}; |
2 | 2 | use once_cell::sync::OnceCell; |
3 | | -use scc::{hash_map::Entry, HashMap}; |
4 | | -use std::sync::atomic::AtomicU32; |
| 3 | +use std::{ |
| 4 | + collections::HashMap, |
| 5 | + sync::{atomic::AtomicU32, Mutex}, |
| 6 | +}; |
| 7 | + |
| 8 | +pub(crate) struct ValueRef(UniqueReentrantMutex); |
| 9 | + |
| 10 | +impl ValueRef { |
| 11 | + pub fn get(&self) -> &UniqueReentrantMutex { |
| 12 | + &self.0 |
| 13 | + } |
| 14 | +} |
| 15 | + |
| 16 | +pub(crate) struct LockMap { |
| 17 | + inner: Mutex<HashMap<String, UniqueReentrantMutex>>, |
| 18 | +} |
| 19 | + |
| 20 | +impl LockMap { |
| 21 | + fn new() -> Self { |
| 22 | + LockMap { |
| 23 | + inner: Mutex::new(HashMap::new()), |
| 24 | + } |
| 25 | + } |
| 26 | + |
| 27 | + pub fn get(&self, key: &str) -> Option<ValueRef> { |
| 28 | + self.inner.lock().unwrap().get(key).cloned().map(ValueRef) |
| 29 | + } |
| 30 | + |
| 31 | + fn get_or_insert( |
| 32 | + &self, |
| 33 | + key: &str, |
| 34 | + f: impl FnOnce() -> UniqueReentrantMutex, |
| 35 | + ) -> UniqueReentrantMutex { |
| 36 | + let mut map = self.inner.lock().unwrap(); |
| 37 | + map.entry(key.to_owned()).or_insert_with(f).clone() |
| 38 | + } |
| 39 | +} |
5 | 40 |
|
6 | 41 | #[derive(Clone)] |
7 | 42 | pub(crate) struct UniqueReentrantMutex { |
@@ -41,11 +76,11 @@ impl UniqueReentrantMutex { |
41 | 76 | } |
42 | 77 |
|
43 | 78 | #[inline] |
44 | | -pub(crate) fn global_locks() -> &'static HashMap<String, UniqueReentrantMutex> { |
| 79 | +pub(crate) fn global_locks() -> &'static LockMap { |
45 | 80 | #[cfg(feature = "test_logging")] |
46 | 81 | let _ = env_logger::builder().try_init(); |
47 | | - static LOCKS: OnceCell<HashMap<String, UniqueReentrantMutex>> = OnceCell::new(); |
48 | | - LOCKS.get_or_init(HashMap::new) |
| 82 | + static LOCKS: OnceCell<LockMap> = OnceCell::new(); |
| 83 | + LOCKS.get_or_init(LockMap::new) |
49 | 84 | } |
50 | 85 |
|
51 | 86 | /// Check if the current thread is holding a serial lock |
@@ -117,17 +152,7 @@ impl UniqueReentrantMutex { |
117 | 152 | } |
118 | 153 |
|
119 | 154 | pub(crate) fn check_new_key(name: &str) { |
120 | | - // Check if a new key is needed. Just need a read lock, which can be done in sync with everyone else |
121 | | - if global_locks().contains(name) { |
122 | | - return; |
123 | | - }; |
124 | | - |
125 | | - // 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 | | - }; |
| 155 | + global_locks().get_or_insert(name, || UniqueReentrantMutex::new_mutex(name)); |
131 | 156 | } |
132 | 157 |
|
133 | 158 | #[cfg(test)] |
|
0 commit comments