1const DEADLOCK_DURATION: std::time::Duration = std::time::Duration::from_secs(10);
6
7#[derive(Default)]
15pub struct Mutex<T>(parking_lot::Mutex<T>);
16
17pub use parking_lot::MutexGuard;
19
20impl<T> Mutex<T> {
21 #[inline(always)]
22 pub fn new(val: T) -> Self {
23 Self(parking_lot::Mutex::new(val))
24 }
25
26 #[inline(always)]
31 #[cfg_attr(debug_assertions, track_caller)]
32 pub fn lock(&self) -> MutexGuard<'_, T> {
33 if cfg!(debug_assertions) {
34 self.0.try_lock_for(DEADLOCK_DURATION).unwrap_or_else(|| {
35 panic!(
36 "DEBUG PANIC: Failed to acquire Mutex after {}s. Deadlock?",
37 DEADLOCK_DURATION.as_secs()
38 )
39 })
40 } else {
41 self.0.lock()
42 }
43 }
44}
45
46pub use parking_lot::MappedRwLockReadGuard as RwLockReadGuard;
50
51pub use parking_lot::MappedRwLockWriteGuard as RwLockWriteGuard;
53
54#[derive(Default)]
62pub struct RwLock<T: ?Sized>(parking_lot::RwLock<T>);
63
64impl<T> RwLock<T> {
65 #[inline(always)]
66 pub fn new(val: T) -> Self {
67 Self(parking_lot::RwLock::new(val))
68 }
69}
70
71impl<T: ?Sized> RwLock<T> {
72 #[inline(always)]
77 #[cfg_attr(debug_assertions, track_caller)]
78 pub fn read(&self) -> RwLockReadGuard<'_, T> {
79 let guard = if cfg!(debug_assertions) {
80 self.0.try_read_for(DEADLOCK_DURATION).unwrap_or_else(|| {
81 panic!(
82 "DEBUG PANIC: Failed to acquire RwLock read after {}s. Deadlock?",
83 DEADLOCK_DURATION.as_secs()
84 )
85 })
86 } else {
87 self.0.read()
88 };
89 parking_lot::RwLockReadGuard::map(guard, |v| v)
90 }
91
92 #[inline(always)]
97 #[cfg_attr(debug_assertions, track_caller)]
98 pub fn write(&self) -> RwLockWriteGuard<'_, T> {
99 let guard = if cfg!(debug_assertions) {
100 self.0.try_write_for(DEADLOCK_DURATION).unwrap_or_else(|| {
101 panic!(
102 "DEBUG PANIC: Failed to acquire RwLock write after {}s. Deadlock?",
103 DEADLOCK_DURATION.as_secs()
104 )
105 })
106 } else {
107 self.0.write()
108 };
109 parking_lot::RwLockWriteGuard::map(guard, |v| v)
110 }
111}
112
113impl<T> Clone for Mutex<T>
116where
117 T: Clone,
118{
119 fn clone(&self) -> Self {
120 Self::new(self.lock().clone())
121 }
122}
123
124#[cfg(test)]
127mod tests {
128 #![allow(clippy::disallowed_methods)] use crate::mutex::Mutex;
131 use std::time::Duration;
132
133 #[test]
134 fn lock_two_different_mutexes_single_thread() {
135 let one = Mutex::new(());
136 let two = Mutex::new(());
137 let _a = one.lock();
138 let _b = two.lock();
139 }
140
141 #[test]
142 fn lock_multiple_threads() {
143 use std::sync::Arc;
144 let one = Arc::new(Mutex::new(()));
145 let our_lock = one.lock();
146 let other_thread = {
147 let one = Arc::clone(&one);
148 std::thread::spawn(move || {
149 let _lock = one.lock();
150 })
151 };
152 std::thread::sleep(Duration::from_millis(200));
153 drop(our_lock);
154 other_thread.join().unwrap();
155 }
156}
157
158#[cfg(not(target_arch = "wasm32"))]
159#[cfg(test)]
160mod tests_rwlock {
161 #![allow(clippy::disallowed_methods)] use crate::mutex::RwLock;
164 use std::time::Duration;
165
166 #[test]
167 fn lock_two_different_rwlocks_single_thread() {
168 let one = RwLock::new(());
169 let two = RwLock::new(());
170 let _a = one.write();
171 let _b = two.write();
172 }
173
174 #[test]
175 fn rwlock_multiple_threads() {
176 use std::sync::Arc;
177 let one = Arc::new(RwLock::new(()));
178 let our_lock = one.write();
179 let other_thread1 = {
180 let one = Arc::clone(&one);
181 std::thread::spawn(move || {
182 let _ = one.write();
183 })
184 };
185 let other_thread2 = {
186 let one = Arc::clone(&one);
187 std::thread::spawn(move || {
188 let _ = one.read();
189 })
190 };
191 std::thread::sleep(Duration::from_millis(200));
192 drop(our_lock);
193 other_thread1.join().unwrap();
194 other_thread2.join().unwrap();
195 }
196
197 #[test]
198 #[should_panic]
199 fn rwlock_write_write_reentrancy() {
200 let one = RwLock::new(());
201 let _a1 = one.write();
202 let _a2 = one.write(); }
204
205 #[test]
206 #[should_panic]
207 fn rwlock_write_read_reentrancy() {
208 let one = RwLock::new(());
209 let _a1 = one.write();
210 let _a2 = one.read(); }
212
213 #[test]
214 #[should_panic]
215 fn rwlock_read_write_reentrancy() {
216 let one = RwLock::new(());
217 let _a1 = one.read();
218 let _a2 = one.write(); }
220
221 #[test]
222 fn rwlock_read_read_reentrancy() {
223 let one = RwLock::new(());
224 let _a1 = one.read();
225 let _a2 = one.read();
228 }
229
230 #[test]
231 fn rwlock_short_read_foreign_read_write_reentrancy() {
232 use std::sync::Arc;
233
234 let lock = Arc::new(RwLock::new(()));
235
236 let t0r0 = lock.read();
238
239 let other_thread = {
241 let lock = Arc::clone(&lock);
242 std::thread::spawn(move || {
243 let _t1r0 = lock.read();
244 })
245 };
246 other_thread.join().unwrap();
247
248 drop(t0r0);
250
251 let _t0w0 = lock.write();
253 }
254
255 #[test]
256 #[should_panic]
257 fn rwlock_read_foreign_read_write_reentrancy() {
258 use std::sync::Arc;
259
260 let lock = Arc::new(RwLock::new(()));
261
262 let _t0r0 = lock.read();
264
265 let other_thread = {
267 let lock = Arc::clone(&lock);
268 std::thread::spawn(move || {
269 let _t1r0 = lock.read();
270 })
271 };
272 other_thread.join().unwrap();
273
274 let _t0w0 = lock.write(); }
277}