1 | #[cfg (all(test, not(target_os = "emscripten" )))] |
2 | mod tests; |
3 | |
4 | use crate::cell::UnsafeCell; |
5 | use crate::fmt; |
6 | use crate::ops::{Deref, DerefMut}; |
7 | use crate::sync::{poison, LockResult, TryLockError, TryLockResult}; |
8 | use crate::sys::locks as sys; |
9 | |
10 | /// A mutual exclusion primitive useful for protecting shared data |
11 | /// |
12 | /// This mutex will block threads waiting for the lock to become available. The |
13 | /// mutex can be created via a [`new`] constructor. Each mutex has a type parameter |
14 | /// which represents the data that it is protecting. The data can only be accessed |
15 | /// through the RAII guards returned from [`lock`] and [`try_lock`], which |
16 | /// guarantees that the data is only ever accessed when the mutex is locked. |
17 | /// |
18 | /// # Poisoning |
19 | /// |
20 | /// The mutexes in this module implement a strategy called "poisoning" where a |
21 | /// mutex is considered poisoned whenever a thread panics while holding the |
22 | /// mutex. Once a mutex is poisoned, all other threads are unable to access the |
23 | /// data by default as it is likely tainted (some invariant is not being |
24 | /// upheld). |
25 | /// |
26 | /// For a mutex, this means that the [`lock`] and [`try_lock`] methods return a |
27 | /// [`Result`] which indicates whether a mutex has been poisoned or not. Most |
28 | /// usage of a mutex will simply [`unwrap()`] these results, propagating panics |
29 | /// among threads to ensure that a possibly invalid invariant is not witnessed. |
30 | /// |
31 | /// A poisoned mutex, however, does not prevent all access to the underlying |
32 | /// data. The [`PoisonError`] type has an [`into_inner`] method which will return |
33 | /// the guard that would have otherwise been returned on a successful lock. This |
34 | /// allows access to the data, despite the lock being poisoned. |
35 | /// |
36 | /// [`new`]: Self::new |
37 | /// [`lock`]: Self::lock |
38 | /// [`try_lock`]: Self::try_lock |
39 | /// [`unwrap()`]: Result::unwrap |
40 | /// [`PoisonError`]: super::PoisonError |
41 | /// [`into_inner`]: super::PoisonError::into_inner |
42 | /// |
43 | /// # Examples |
44 | /// |
45 | /// ``` |
46 | /// use std::sync::{Arc, Mutex}; |
47 | /// use std::thread; |
48 | /// use std::sync::mpsc::channel; |
49 | /// |
50 | /// const N: usize = 10; |
51 | /// |
52 | /// // Spawn a few threads to increment a shared variable (non-atomically), and |
53 | /// // let the main thread know once all increments are done. |
54 | /// // |
55 | /// // Here we're using an Arc to share memory among threads, and the data inside |
56 | /// // the Arc is protected with a mutex. |
57 | /// let data = Arc::new(Mutex::new(0)); |
58 | /// |
59 | /// let (tx, rx) = channel(); |
60 | /// for _ in 0..N { |
61 | /// let (data, tx) = (Arc::clone(&data), tx.clone()); |
62 | /// thread::spawn(move || { |
63 | /// // The shared state can only be accessed once the lock is held. |
64 | /// // Our non-atomic increment is safe because we're the only thread |
65 | /// // which can access the shared state when the lock is held. |
66 | /// // |
67 | /// // We unwrap() the return value to assert that we are not expecting |
68 | /// // threads to ever fail while holding the lock. |
69 | /// let mut data = data.lock().unwrap(); |
70 | /// *data += 1; |
71 | /// if *data == N { |
72 | /// tx.send(()).unwrap(); |
73 | /// } |
74 | /// // the lock is unlocked here when `data` goes out of scope. |
75 | /// }); |
76 | /// } |
77 | /// |
78 | /// rx.recv().unwrap(); |
79 | /// ``` |
80 | /// |
81 | /// To recover from a poisoned mutex: |
82 | /// |
83 | /// ``` |
84 | /// use std::sync::{Arc, Mutex}; |
85 | /// use std::thread; |
86 | /// |
87 | /// let lock = Arc::new(Mutex::new(0_u32)); |
88 | /// let lock2 = Arc::clone(&lock); |
89 | /// |
90 | /// let _ = thread::spawn(move || -> () { |
91 | /// // This thread will acquire the mutex first, unwrapping the result of |
92 | /// // `lock` because the lock has not been poisoned. |
93 | /// let _guard = lock2.lock().unwrap(); |
94 | /// |
95 | /// // This panic while holding the lock (`_guard` is in scope) will poison |
96 | /// // the mutex. |
97 | /// panic!(); |
98 | /// }).join(); |
99 | /// |
100 | /// // The lock is poisoned by this point, but the returned result can be |
101 | /// // pattern matched on to return the underlying guard on both branches. |
102 | /// let mut guard = match lock.lock() { |
103 | /// Ok(guard) => guard, |
104 | /// Err(poisoned) => poisoned.into_inner(), |
105 | /// }; |
106 | /// |
107 | /// *guard += 1; |
108 | /// ``` |
109 | /// |
110 | /// To unlock a mutex guard sooner than the end of the enclosing scope, |
111 | /// either create an inner scope or drop the guard manually. |
112 | /// |
113 | /// ``` |
114 | /// use std::sync::{Arc, Mutex}; |
115 | /// use std::thread; |
116 | /// |
117 | /// const N: usize = 3; |
118 | /// |
119 | /// let data_mutex = Arc::new(Mutex::new(vec![1, 2, 3, 4])); |
120 | /// let res_mutex = Arc::new(Mutex::new(0)); |
121 | /// |
122 | /// let mut threads = Vec::with_capacity(N); |
123 | /// (0..N).for_each(|_| { |
124 | /// let data_mutex_clone = Arc::clone(&data_mutex); |
125 | /// let res_mutex_clone = Arc::clone(&res_mutex); |
126 | /// |
127 | /// threads.push(thread::spawn(move || { |
128 | /// // Here we use a block to limit the lifetime of the lock guard. |
129 | /// let result = { |
130 | /// let mut data = data_mutex_clone.lock().unwrap(); |
131 | /// // This is the result of some important and long-ish work. |
132 | /// let result = data.iter().fold(0, |acc, x| acc + x * 2); |
133 | /// data.push(result); |
134 | /// result |
135 | /// // The mutex guard gets dropped here, together with any other values |
136 | /// // created in the critical section. |
137 | /// }; |
138 | /// // The guard created here is a temporary dropped at the end of the statement, i.e. |
139 | /// // the lock would not remain being held even if the thread did some additional work. |
140 | /// *res_mutex_clone.lock().unwrap() += result; |
141 | /// })); |
142 | /// }); |
143 | /// |
144 | /// let mut data = data_mutex.lock().unwrap(); |
145 | /// // This is the result of some important and long-ish work. |
146 | /// let result = data.iter().fold(0, |acc, x| acc + x * 2); |
147 | /// data.push(result); |
148 | /// // We drop the `data` explicitly because it's not necessary anymore and the |
149 | /// // thread still has work to do. This allows other threads to start working on |
150 | /// // the data immediately, without waiting for the rest of the unrelated work |
151 | /// // to be done here. |
152 | /// // |
153 | /// // It's even more important here than in the threads because we `.join` the |
154 | /// // threads after that. If we had not dropped the mutex guard, a thread could |
155 | /// // be waiting forever for it, causing a deadlock. |
156 | /// // As in the threads, a block could have been used instead of calling the |
157 | /// // `drop` function. |
158 | /// drop(data); |
159 | /// // Here the mutex guard is not assigned to a variable and so, even if the |
160 | /// // scope does not end after this line, the mutex is still released: there is |
161 | /// // no deadlock. |
162 | /// *res_mutex.lock().unwrap() += result; |
163 | /// |
164 | /// threads.into_iter().for_each(|thread| { |
165 | /// thread |
166 | /// .join() |
167 | /// .expect("The thread creating or execution failed !" ) |
168 | /// }); |
169 | /// |
170 | /// assert_eq!(*res_mutex.lock().unwrap(), 800); |
171 | /// ``` |
172 | /// |
173 | #[stable (feature = "rust1" , since = "1.0.0" )] |
174 | #[cfg_attr (not(test), rustc_diagnostic_item = "Mutex" )] |
175 | pub struct Mutex<T: ?Sized> { |
176 | inner: sys::Mutex, |
177 | poison: poison::Flag, |
178 | data: UnsafeCell<T>, |
179 | } |
180 | |
181 | // these are the only places where `T: Send` matters; all other |
182 | // functionality works fine on a single thread. |
183 | #[stable (feature = "rust1" , since = "1.0.0" )] |
184 | unsafe impl<T: ?Sized + Send> Send for Mutex<T> {} |
185 | #[stable (feature = "rust1" , since = "1.0.0" )] |
186 | unsafe impl<T: ?Sized + Send> Sync for Mutex<T> {} |
187 | |
188 | /// An RAII implementation of a "scoped lock" of a mutex. When this structure is |
189 | /// dropped (falls out of scope), the lock will be unlocked. |
190 | /// |
191 | /// The data protected by the mutex can be accessed through this guard via its |
192 | /// [`Deref`] and [`DerefMut`] implementations. |
193 | /// |
194 | /// This structure is created by the [`lock`] and [`try_lock`] methods on |
195 | /// [`Mutex`]. |
196 | /// |
197 | /// [`lock`]: Mutex::lock |
198 | /// [`try_lock`]: Mutex::try_lock |
199 | #[must_use = "if unused the Mutex will immediately unlock" ] |
200 | #[must_not_suspend = "holding a MutexGuard across suspend \ |
201 | points can cause deadlocks, delays, \ |
202 | and cause Futures to not implement `Send`" ] |
203 | #[stable (feature = "rust1" , since = "1.0.0" )] |
204 | #[clippy::has_significant_drop] |
205 | #[cfg_attr (not(test), rustc_diagnostic_item = "MutexGuard" )] |
206 | pub struct MutexGuard<'a, T: ?Sized + 'a> { |
207 | lock: &'a Mutex<T>, |
208 | poison: poison::Guard, |
209 | } |
210 | |
211 | #[stable (feature = "rust1" , since = "1.0.0" )] |
212 | impl<T: ?Sized> !Send for MutexGuard<'_, T> {} |
213 | #[stable (feature = "mutexguard" , since = "1.19.0" )] |
214 | unsafe impl<T: ?Sized + Sync> Sync for MutexGuard<'_, T> {} |
215 | |
216 | impl<T> Mutex<T> { |
217 | /// Creates a new mutex in an unlocked state ready for use. |
218 | /// |
219 | /// # Examples |
220 | /// |
221 | /// ``` |
222 | /// use std::sync::Mutex; |
223 | /// |
224 | /// let mutex = Mutex::new(0); |
225 | /// ``` |
226 | #[stable (feature = "rust1" , since = "1.0.0" )] |
227 | #[rustc_const_stable (feature = "const_locks" , since = "1.63.0" )] |
228 | #[inline ] |
229 | pub const fn new(t: T) -> Mutex<T> { |
230 | Mutex { inner: sys::Mutex::new(), poison: poison::Flag::new(), data: UnsafeCell::new(t) } |
231 | } |
232 | } |
233 | |
234 | impl<T: ?Sized> Mutex<T> { |
235 | /// Acquires a mutex, blocking the current thread until it is able to do so. |
236 | /// |
237 | /// This function will block the local thread until it is available to acquire |
238 | /// the mutex. Upon returning, the thread is the only thread with the lock |
239 | /// held. An RAII guard is returned to allow scoped unlock of the lock. When |
240 | /// the guard goes out of scope, the mutex will be unlocked. |
241 | /// |
242 | /// The exact behavior on locking a mutex in the thread which already holds |
243 | /// the lock is left unspecified. However, this function will not return on |
244 | /// the second call (it might panic or deadlock, for example). |
245 | /// |
246 | /// # Errors |
247 | /// |
248 | /// If another user of this mutex panicked while holding the mutex, then |
249 | /// this call will return an error once the mutex is acquired. |
250 | /// |
251 | /// # Panics |
252 | /// |
253 | /// This function might panic when called if the lock is already held by |
254 | /// the current thread. |
255 | /// |
256 | /// # Examples |
257 | /// |
258 | /// ``` |
259 | /// use std::sync::{Arc, Mutex}; |
260 | /// use std::thread; |
261 | /// |
262 | /// let mutex = Arc::new(Mutex::new(0)); |
263 | /// let c_mutex = Arc::clone(&mutex); |
264 | /// |
265 | /// thread::spawn(move || { |
266 | /// *c_mutex.lock().unwrap() = 10; |
267 | /// }).join().expect("thread::spawn failed" ); |
268 | /// assert_eq!(*mutex.lock().unwrap(), 10); |
269 | /// ``` |
270 | #[stable (feature = "rust1" , since = "1.0.0" )] |
271 | pub fn lock(&self) -> LockResult<MutexGuard<'_, T>> { |
272 | unsafe { |
273 | self.inner.lock(); |
274 | MutexGuard::new(self) |
275 | } |
276 | } |
277 | |
278 | /// Attempts to acquire this lock. |
279 | /// |
280 | /// If the lock could not be acquired at this time, then [`Err`] is returned. |
281 | /// Otherwise, an RAII guard is returned. The lock will be unlocked when the |
282 | /// guard is dropped. |
283 | /// |
284 | /// This function does not block. |
285 | /// |
286 | /// # Errors |
287 | /// |
288 | /// If another user of this mutex panicked while holding the mutex, then |
289 | /// this call will return the [`Poisoned`] error if the mutex would |
290 | /// otherwise be acquired. |
291 | /// |
292 | /// If the mutex could not be acquired because it is already locked, then |
293 | /// this call will return the [`WouldBlock`] error. |
294 | /// |
295 | /// [`Poisoned`]: TryLockError::Poisoned |
296 | /// [`WouldBlock`]: TryLockError::WouldBlock |
297 | /// |
298 | /// # Examples |
299 | /// |
300 | /// ``` |
301 | /// use std::sync::{Arc, Mutex}; |
302 | /// use std::thread; |
303 | /// |
304 | /// let mutex = Arc::new(Mutex::new(0)); |
305 | /// let c_mutex = Arc::clone(&mutex); |
306 | /// |
307 | /// thread::spawn(move || { |
308 | /// let mut lock = c_mutex.try_lock(); |
309 | /// if let Ok(ref mut mutex) = lock { |
310 | /// **mutex = 10; |
311 | /// } else { |
312 | /// println!("try_lock failed" ); |
313 | /// } |
314 | /// }).join().expect("thread::spawn failed" ); |
315 | /// assert_eq!(*mutex.lock().unwrap(), 10); |
316 | /// ``` |
317 | #[stable (feature = "rust1" , since = "1.0.0" )] |
318 | pub fn try_lock(&self) -> TryLockResult<MutexGuard<'_, T>> { |
319 | unsafe { |
320 | if self.inner.try_lock() { |
321 | Ok(MutexGuard::new(self)?) |
322 | } else { |
323 | Err(TryLockError::WouldBlock) |
324 | } |
325 | } |
326 | } |
327 | |
328 | /// Immediately drops the guard, and consequently unlocks the mutex. |
329 | /// |
330 | /// This function is equivalent to calling [`drop`] on the guard but is more self-documenting. |
331 | /// Alternately, the guard will be automatically dropped when it goes out of scope. |
332 | /// |
333 | /// ``` |
334 | /// #![feature(mutex_unlock)] |
335 | /// |
336 | /// use std::sync::Mutex; |
337 | /// let mutex = Mutex::new(0); |
338 | /// |
339 | /// let mut guard = mutex.lock().unwrap(); |
340 | /// *guard += 20; |
341 | /// Mutex::unlock(guard); |
342 | /// ``` |
343 | #[unstable (feature = "mutex_unlock" , issue = "81872" )] |
344 | pub fn unlock(guard: MutexGuard<'_, T>) { |
345 | drop(guard); |
346 | } |
347 | |
348 | /// Determines whether the mutex is poisoned. |
349 | /// |
350 | /// If another thread is active, the mutex can still become poisoned at any |
351 | /// time. You should not trust a `false` value for program correctness |
352 | /// without additional synchronization. |
353 | /// |
354 | /// # Examples |
355 | /// |
356 | /// ``` |
357 | /// use std::sync::{Arc, Mutex}; |
358 | /// use std::thread; |
359 | /// |
360 | /// let mutex = Arc::new(Mutex::new(0)); |
361 | /// let c_mutex = Arc::clone(&mutex); |
362 | /// |
363 | /// let _ = thread::spawn(move || { |
364 | /// let _lock = c_mutex.lock().unwrap(); |
365 | /// panic!(); // the mutex gets poisoned |
366 | /// }).join(); |
367 | /// assert_eq!(mutex.is_poisoned(), true); |
368 | /// ``` |
369 | #[inline ] |
370 | #[stable (feature = "sync_poison" , since = "1.2.0" )] |
371 | pub fn is_poisoned(&self) -> bool { |
372 | self.poison.get() |
373 | } |
374 | |
375 | /// Clear the poisoned state from a mutex |
376 | /// |
377 | /// If the mutex is poisoned, it will remain poisoned until this function is called. This |
378 | /// allows recovering from a poisoned state and marking that it has recovered. For example, if |
379 | /// the value is overwritten by a known-good value, then the mutex can be marked as |
380 | /// un-poisoned. Or possibly, the value could be inspected to determine if it is in a |
381 | /// consistent state, and if so the poison is removed. |
382 | /// |
383 | /// # Examples |
384 | /// |
385 | /// ``` |
386 | /// use std::sync::{Arc, Mutex}; |
387 | /// use std::thread; |
388 | /// |
389 | /// let mutex = Arc::new(Mutex::new(0)); |
390 | /// let c_mutex = Arc::clone(&mutex); |
391 | /// |
392 | /// let _ = thread::spawn(move || { |
393 | /// let _lock = c_mutex.lock().unwrap(); |
394 | /// panic!(); // the mutex gets poisoned |
395 | /// }).join(); |
396 | /// |
397 | /// assert_eq!(mutex.is_poisoned(), true); |
398 | /// let x = mutex.lock().unwrap_or_else(|mut e| { |
399 | /// **e.get_mut() = 1; |
400 | /// mutex.clear_poison(); |
401 | /// e.into_inner() |
402 | /// }); |
403 | /// assert_eq!(mutex.is_poisoned(), false); |
404 | /// assert_eq!(*x, 1); |
405 | /// ``` |
406 | #[inline ] |
407 | #[stable (feature = "mutex_unpoison" , since = "1.77.0" )] |
408 | pub fn clear_poison(&self) { |
409 | self.poison.clear(); |
410 | } |
411 | |
412 | /// Consumes this mutex, returning the underlying data. |
413 | /// |
414 | /// # Errors |
415 | /// |
416 | /// If another user of this mutex panicked while holding the mutex, then |
417 | /// this call will return an error instead. |
418 | /// |
419 | /// # Examples |
420 | /// |
421 | /// ``` |
422 | /// use std::sync::Mutex; |
423 | /// |
424 | /// let mutex = Mutex::new(0); |
425 | /// assert_eq!(mutex.into_inner().unwrap(), 0); |
426 | /// ``` |
427 | #[stable (feature = "mutex_into_inner" , since = "1.6.0" )] |
428 | pub fn into_inner(self) -> LockResult<T> |
429 | where |
430 | T: Sized, |
431 | { |
432 | let data = self.data.into_inner(); |
433 | poison::map_result(self.poison.borrow(), |()| data) |
434 | } |
435 | |
436 | /// Returns a mutable reference to the underlying data. |
437 | /// |
438 | /// Since this call borrows the `Mutex` mutably, no actual locking needs to |
439 | /// take place -- the mutable borrow statically guarantees no locks exist. |
440 | /// |
441 | /// # Errors |
442 | /// |
443 | /// If another user of this mutex panicked while holding the mutex, then |
444 | /// this call will return an error instead. |
445 | /// |
446 | /// # Examples |
447 | /// |
448 | /// ``` |
449 | /// use std::sync::Mutex; |
450 | /// |
451 | /// let mut mutex = Mutex::new(0); |
452 | /// *mutex.get_mut().unwrap() = 10; |
453 | /// assert_eq!(*mutex.lock().unwrap(), 10); |
454 | /// ``` |
455 | #[stable (feature = "mutex_get_mut" , since = "1.6.0" )] |
456 | pub fn get_mut(&mut self) -> LockResult<&mut T> { |
457 | let data = self.data.get_mut(); |
458 | poison::map_result(self.poison.borrow(), |()| data) |
459 | } |
460 | } |
461 | |
462 | #[stable (feature = "mutex_from" , since = "1.24.0" )] |
463 | impl<T> From<T> for Mutex<T> { |
464 | /// Creates a new mutex in an unlocked state ready for use. |
465 | /// This is equivalent to [`Mutex::new`]. |
466 | fn from(t: T) -> Self { |
467 | Mutex::new(t) |
468 | } |
469 | } |
470 | |
471 | #[stable (feature = "mutex_default" , since = "1.10.0" )] |
472 | impl<T: ?Sized + Default> Default for Mutex<T> { |
473 | /// Creates a `Mutex<T>`, with the `Default` value for T. |
474 | fn default() -> Mutex<T> { |
475 | Mutex::new(Default::default()) |
476 | } |
477 | } |
478 | |
479 | #[stable (feature = "rust1" , since = "1.0.0" )] |
480 | impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> { |
481 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
482 | let mut d: DebugStruct<'_, '_> = f.debug_struct(name:"Mutex" ); |
483 | match self.try_lock() { |
484 | Ok(guard: MutexGuard<'_, T>) => { |
485 | d.field(name:"data" , &&*guard); |
486 | } |
487 | Err(TryLockError::Poisoned(err: PoisonError>)) => { |
488 | d.field(name:"data" , &&**err.get_ref()); |
489 | } |
490 | Err(TryLockError::WouldBlock) => { |
491 | d.field(name:"data" , &format_args!("<locked>" )); |
492 | } |
493 | } |
494 | d.field(name:"poisoned" , &self.poison.get()); |
495 | d.finish_non_exhaustive() |
496 | } |
497 | } |
498 | |
499 | impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> { |
500 | unsafe fn new(lock: &'mutex Mutex<T>) -> LockResult<MutexGuard<'mutex, T>> { |
501 | poison::map_result(result:lock.poison.guard(), |guard: Guard| MutexGuard { lock, poison: guard }) |
502 | } |
503 | } |
504 | |
505 | #[stable (feature = "rust1" , since = "1.0.0" )] |
506 | impl<T: ?Sized> Deref for MutexGuard<'_, T> { |
507 | type Target = T; |
508 | |
509 | fn deref(&self) -> &T { |
510 | unsafe { &*self.lock.data.get() } |
511 | } |
512 | } |
513 | |
514 | #[stable (feature = "rust1" , since = "1.0.0" )] |
515 | impl<T: ?Sized> DerefMut for MutexGuard<'_, T> { |
516 | fn deref_mut(&mut self) -> &mut T { |
517 | unsafe { &mut *self.lock.data.get() } |
518 | } |
519 | } |
520 | |
521 | #[stable (feature = "rust1" , since = "1.0.0" )] |
522 | impl<T: ?Sized> Drop for MutexGuard<'_, T> { |
523 | #[inline ] |
524 | fn drop(&mut self) { |
525 | unsafe { |
526 | self.lock.poison.done(&self.poison); |
527 | self.lock.inner.unlock(); |
528 | } |
529 | } |
530 | } |
531 | |
532 | #[stable (feature = "std_debug" , since = "1.16.0" )] |
533 | impl<T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'_, T> { |
534 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
535 | fmt::Debug::fmt(&**self, f) |
536 | } |
537 | } |
538 | |
539 | #[stable (feature = "std_guard_impls" , since = "1.20.0" )] |
540 | impl<T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'_, T> { |
541 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
542 | (**self).fmt(f) |
543 | } |
544 | } |
545 | |
546 | pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { |
547 | &guard.lock.inner |
548 | } |
549 | |
550 | pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag { |
551 | &guard.lock.poison |
552 | } |
553 | |