1use crate::raw_mutex::RawMutex;
2
3pub type Mutex<T> = lock_api::Mutex<RawMutex, T>;
65
66pub type MutexGuard<'a, T> = lock_api::MutexGuard<'a, RawMutex, T>;
72
73pub type MappedMutexGuard<'a, T> = lock_api::MappedMutexGuard<'a, RawMutex, T>;
81
82#[cfg(test)]
83mod tests {
84 use crate::{Condvar, MappedMutexGuard, Mutex, MutexGuard};
85 use std::collections::HashMap;
86 use std::ops::Deref;
87 use std::sync::Arc;
88 use std::sync::atomic::{AtomicUsize, Ordering};
89 use std::sync::mpsc::channel;
90 use std::thread;
91
92 #[cfg(feature = "serde")]
93 use postcard::{from_bytes, to_stdvec};
94
95 struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
96
97 #[derive(Eq, PartialEq, Debug)]
98 struct NonCopy(i32);
99
100 #[test]
101 fn smoke() {
102 let m = Mutex::new(());
103 drop(m.lock());
104 drop(m.lock());
105 }
106
107 #[test]
108 fn lots_and_lots() {
109 const J: u32 = if cfg!(miri) { 200 } else { 1000 };
110 const K: u32 = 3;
111
112 let m = Arc::new(Mutex::new(0));
113
114 fn inc(m: &Mutex<u32>) {
115 for _ in 0..J {
116 *m.lock() += 1;
117 }
118 }
119
120 let (tx, rx) = channel();
121 for _ in 0..K {
122 let tx2 = tx.clone();
123 let m2 = m.clone();
124 thread::spawn(move || {
125 inc(&m2);
126 tx2.send(()).unwrap();
127 });
128 let tx2 = tx.clone();
129 let m2 = m.clone();
130 thread::spawn(move || {
131 inc(&m2);
132 tx2.send(()).unwrap();
133 });
134 }
135
136 drop(tx);
137 for _ in 0..2 * K {
138 rx.recv().unwrap();
139 }
140 assert_eq!(*m.lock(), J * K * 2);
141 }
142
143 #[test]
144 fn try_lock() {
145 let m = Mutex::new(());
146 let guard = m.try_lock().unwrap();
147 assert!(m.try_lock().is_none());
148 drop(guard);
149 assert!(m.try_lock().is_some());
150 }
151
152 #[test]
153 fn test_into_inner() {
154 let m = Mutex::new(NonCopy(10));
155 assert_eq!(m.into_inner(), NonCopy(10));
156 }
157
158 #[test]
159 fn test_into_inner_drop() {
160 struct Foo(Arc<AtomicUsize>);
161 impl Drop for Foo {
162 fn drop(&mut self) {
163 self.0.fetch_add(1, Ordering::SeqCst);
164 }
165 }
166 let num_drops = Arc::new(AtomicUsize::new(0));
167 let m = Mutex::new(Foo(num_drops.clone()));
168 assert_eq!(num_drops.load(Ordering::SeqCst), 0);
169 {
170 let _inner = m.into_inner();
171 assert_eq!(num_drops.load(Ordering::SeqCst), 0);
172 }
173 assert_eq!(num_drops.load(Ordering::SeqCst), 1);
174 }
175
176 #[test]
177 fn test_get_mut() {
178 let mut m = Mutex::new(NonCopy(10));
179 *m.get_mut() = NonCopy(20);
180 assert_eq!(m.into_inner(), NonCopy(20));
181 }
182
183 #[test]
184 fn test_mutex_arc_condvar() {
185 let packet = Packet(Arc::new((Mutex::new(false), Condvar::new())));
186 let packet2 = Packet(packet.0.clone());
187 let (tx, rx) = channel();
188 let _t = thread::spawn(move || {
189 rx.recv().unwrap();
191 let (lock, cvar) = &*packet2.0;
192 let mut lock = lock.lock();
193 *lock = true;
194 cvar.notify_one();
195 });
196
197 let (lock, cvar) = &*packet.0;
198 let mut lock = lock.lock();
199 tx.send(()).unwrap();
200 assert!(!*lock);
201 while !*lock {
202 cvar.wait(&mut lock);
203 }
204 }
205
206 #[test]
207 fn test_mutex_arc_nested() {
208 let arc = Arc::new(Mutex::new(1));
211 let arc2 = Arc::new(Mutex::new(arc));
212 let (tx, rx) = channel();
213 let _t = thread::spawn(move || {
214 let lock = arc2.lock();
215 let lock2 = lock.lock();
216 assert_eq!(*lock2, 1);
217 tx.send(()).unwrap();
218 });
219 rx.recv().unwrap();
220 }
221
222 #[test]
223 fn test_mutex_arc_access_in_unwind() {
224 let arc = Arc::new(Mutex::new(1));
225 let arc2 = arc.clone();
226 let _ = thread::spawn(move || {
227 struct Unwinder {
228 i: Arc<Mutex<i32>>,
229 }
230 impl Drop for Unwinder {
231 fn drop(&mut self) {
232 *self.i.lock() += 1;
233 }
234 }
235 let _u = Unwinder { i: arc2 };
236 panic!();
237 })
238 .join();
239 let lock = arc.lock();
240 assert_eq!(*lock, 2);
241 }
242
243 #[test]
244 fn test_mutex_unsized() {
245 let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]);
246 {
247 let b = &mut *mutex.lock();
248 b[0] = 4;
249 b[2] = 5;
250 }
251 let comp: &[i32] = &[4, 2, 5];
252 assert_eq!(&*mutex.lock(), comp);
253 }
254
255 #[test]
256 fn test_mutexguard_sync() {
257 fn sync<T: Sync>(_: T) {}
258
259 let mutex = Mutex::new(());
260 sync(mutex.lock());
261 }
262
263 #[test]
264 fn test_mutex_debug() {
265 let mutex = Mutex::new(vec![0u8, 10]);
266
267 assert_eq!(format!("{:?}", mutex), "Mutex { data: [0, 10] }");
268 let _lock = mutex.lock();
269 assert_eq!(format!("{:?}", mutex), "Mutex { data: <locked> }");
270 }
271
272 #[cfg(feature = "serde")]
273 #[test]
274 fn test_serde() {
275 let contents: Vec<u8> = vec![0, 1, 2];
276 let mutex = Mutex::new(contents.clone());
277
278 let serialized = to_stdvec(&mutex).unwrap();
279 let deserialized: Mutex<Vec<u8>> = from_bytes(&serialized).unwrap();
280
281 assert_eq!(*(mutex.lock()), *(deserialized.lock()));
282 assert_eq!(contents, *(deserialized.lock()));
283 }
284
285 #[test]
286 fn test_map_or_err_not_mapped() {
287 let mut map = HashMap::new();
288 map.insert("hello".to_string(), "world".to_string());
289
290 let mutex = Mutex::new(map);
291 let guard = mutex.lock();
292 let guard = match MutexGuard::try_map_or_err(guard, |the_map| {
293 the_map.get_mut("hello2").ok_or(12345i32)
294 }) {
295 Ok(_) => unreachable!(),
296 Err((guard, data)) => {
297 assert_eq!(data, 12345i32);
298 assert_eq!(guard.get("hello"), Some(&"world".to_string()));
299 guard
300 }
301 };
302
303 let mapped_guard = match MutexGuard::try_map_or_err(guard, |the_map| {
305 the_map.get_mut("hello").ok_or("unreachable")
306 }) {
307 Ok(mapped_guard) => mapped_guard,
308 Err((_, _)) => unreachable!(),
309 };
310
311 assert_eq!(mapped_guard.as_str(), "world");
312
313 match MappedMutexGuard::try_map_or_err(mapped_guard, |the_string| {
314 if the_string != "world" {
315 Ok(the_string.as_mut_str())
317 } else {
318 Err(45678i32)
319 }
320 }) {
321 Ok(_) => unreachable!(),
322 Err((guard, err)) => {
323 assert_eq!(guard.as_str(), "world");
324 assert_eq!(err, 45678i32);
325 }
326 };
327 }
328
329 #[test]
330 fn test_map_or_err_mapped() {
331 let mut map = HashMap::new();
332 map.insert("hello".to_string(), "world".to_string());
333
334 let mutex = Mutex::new(map);
335 let guard = mutex.lock();
336 let mapped_guard = match MutexGuard::try_map_or_err(guard, |the_map| {
337 the_map.get_mut("hello").ok_or("unreachable")
338 }) {
339 Ok(mapped_guard) => mapped_guard,
340 Err((_, _)) => unreachable!(),
341 };
342
343 assert_eq!(mapped_guard.as_str(), "world");
344
345 match MappedMutexGuard::try_map_or_err(mapped_guard, |the_string| {
346 if the_string == "world" {
347 Ok(the_string.as_mut_str())
348 } else {
349 Err("unreachable")
350 }
351 }) {
352 Ok(mapped_guard) => assert_eq!(mapped_guard.deref(), "world"),
353 Err((_, _)) => unreachable!(),
354 };
355 }
356}