1pub use parking_lot as raw;
43
44#[cfg(debug_assertions)]
45pub use tracing::{
46 FairMutex, FairMutexGuard, MappedFairMutexGuard, MappedMutexGuard, MappedReentrantMutexGuard,
47 MappedRwLockReadGuard, MappedRwLockWriteGuard, Mutex, MutexGuard, Once, OnceState,
48 ReentrantMutex, ReentrantMutexGuard, RwLock, RwLockReadGuard, RwLockUpgradableReadGuard,
49 RwLockWriteGuard,
50};
51
52#[cfg(not(debug_assertions))]
53pub use parking_lot::{
54 FairMutex, FairMutexGuard, MappedFairMutexGuard, MappedMutexGuard, MappedReentrantMutexGuard,
55 MappedRwLockReadGuard, MappedRwLockWriteGuard, Mutex, MutexGuard, Once, OnceState,
56 ReentrantMutex, ReentrantMutexGuard, RwLock, RwLockReadGuard, RwLockUpgradableReadGuard,
57 RwLockWriteGuard,
58};
59
60pub mod tracing {
62 pub use parking_lot::OnceState;
63
64 use crate::lockapi::TracingWrapper;
65 use crate::LazyMutexId;
66
67 type RawFairMutex = TracingWrapper<parking_lot::RawFairMutex>;
68 type RawMutex = TracingWrapper<parking_lot::RawMutex>;
69 type RawRwLock = TracingWrapper<parking_lot::RawRwLock>;
70
71 pub type FairMutex<T> = lock_api::Mutex<RawFairMutex, T>;
73 pub type FairMutexGuard<'a, T> = lock_api::MutexGuard<'a, RawFairMutex, T>;
75 pub type MappedFairMutexGuard<'a, T> = lock_api::MappedMutexGuard<'a, RawFairMutex, T>;
77
78 pub type Mutex<T> = lock_api::Mutex<RawMutex, T>;
80 pub type MutexGuard<'a, T> = lock_api::MutexGuard<'a, RawMutex, T>;
82 pub type MappedMutexGuard<'a, T> = lock_api::MappedMutexGuard<'a, RawMutex, T>;
84
85 pub type ReentrantMutex<T> = lock_api::ReentrantMutex<RawMutex, parking_lot::RawThreadId, T>;
91 pub type ReentrantMutexGuard<'a, T> =
93 lock_api::ReentrantMutexGuard<'a, RawMutex, parking_lot::RawThreadId, T>;
94 pub type MappedReentrantMutexGuard<'a, T> =
96 lock_api::MappedReentrantMutexGuard<'a, RawMutex, parking_lot::RawThreadId, T>;
97
98 pub type RwLock<T> = lock_api::RwLock<RawRwLock, T>;
100 pub type RwLockReadGuard<'a, T> = lock_api::RwLockReadGuard<'a, RawRwLock, T>;
102 pub type RwLockUpgradableReadGuard<'a, T> =
104 lock_api::RwLockUpgradableReadGuard<'a, RawRwLock, T>;
105 pub type RwLockWriteGuard<'a, T> = lock_api::RwLockWriteGuard<'a, RawRwLock, T>;
107 pub type MappedRwLockReadGuard<'a, T> = lock_api::MappedRwLockReadGuard<'a, RawRwLock, T>;
109 pub type MappedRwLockWriteGuard<'a, T> = lock_api::MappedRwLockWriteGuard<'a, RawRwLock, T>;
111
112 #[derive(Debug, Default)]
114 pub struct Once {
115 inner: parking_lot::Once,
116 id: LazyMutexId,
117 }
118
119 impl Once {
120 pub const fn new() -> Self {
122 Self {
123 inner: parking_lot::Once::new(),
124 id: LazyMutexId::new(),
125 }
126 }
127
128 pub fn state(&self) -> OnceState {
130 self.inner.state()
131 }
132
133 pub fn call_once(&self, f: impl FnOnce()) {
141 let _borrow = self.id.get_borrowed();
142 self.inner.call_once(f);
143 }
144
145 pub fn call_once_force(&self, f: impl FnOnce(OnceState)) {
149 let _borrow = self.id.get_borrowed();
150 self.inner.call_once_force(f);
151 }
152 }
153}
154
155#[cfg(test)]
156mod tests {
157 use std::sync::Arc;
158 use std::thread;
159
160 use super::tracing;
161
162 #[test]
163 fn test_mutex_usage() {
164 let mutex = Arc::new(tracing::Mutex::new(()));
165 let local_lock = mutex.lock();
166 drop(local_lock);
167
168 thread::spawn(move || {
169 let _remote_lock = mutex.lock();
170 })
171 .join()
172 .unwrap();
173 }
174
175 #[test]
176 #[should_panic]
177 fn test_mutex_conflict() {
178 let mutexes = [
179 tracing::Mutex::new(()),
180 tracing::Mutex::new(()),
181 tracing::Mutex::new(()),
182 ];
183
184 for i in 0..3 {
185 let _first_lock = mutexes[i].lock();
186 let _second_lock = mutexes[(i + 1) % 3].lock();
187 }
188 }
189
190 #[test]
191 fn test_rwlock_usage() {
192 let lock = Arc::new(tracing::RwLock::new(()));
193 let lock2 = Arc::clone(&lock);
194
195 let _read_lock = lock.read();
196
197 thread::spawn(move || {
199 let _read_lock = lock2.read();
200 })
201 .join()
202 .unwrap();
203 }
204
205 #[test]
206 fn test_rwlock_upgradable_read_usage() {
207 let lock = tracing::RwLock::new(());
208
209 let upgradable_guard: tracing::RwLockUpgradableReadGuard<'_, _> = lock.upgradable_read();
211
212 let _write_guard: tracing::RwLockWriteGuard<'_, _> =
214 tracing::RwLockUpgradableReadGuard::upgrade(upgradable_guard);
215 }
216
217 #[test]
218 fn test_once_usage() {
219 let once = Arc::new(tracing::Once::new());
220 let once_clone = once.clone();
221
222 assert!(!once_clone.state().done());
223
224 let handle = thread::spawn(move || {
225 assert!(!once_clone.state().done());
226
227 once_clone.call_once(|| {});
228
229 assert!(once_clone.state().done());
230 });
231
232 handle.join().unwrap();
233
234 assert!(once.state().done());
235 }
236}