#[cfg(all(test, not(target_os = "emscripten")))] mod tests; use crate::cell::UnsafeCell; use crate::fmt; use crate::ops::{Deref, DerefMut}; use crate::sync::{poison, LockResult, TryLockError, TryLockResult}; use crate::sys_common::mutex as sys; /// A mutual exclusion primitive useful for protecting shared data /// /// This mutex will block threads waiting for the lock to become available. The /// mutex can be created via a [`new`] constructor. Each mutex has a type parameter /// which represents the data that it is protecting. The data can only be accessed /// through the RAII guards returned from [`lock`] and [`try_lock`], which /// guarantees that the data is only ever accessed when the mutex is locked. /// /// # Poisoning /// /// The mutexes in this module implement a strategy called "poisoning" where a /// mutex is considered poisoned whenever a thread panics while holding the /// mutex. Once a mutex is poisoned, all other threads are unable to access the /// data by default as it is likely tainted (some invariant is not being /// upheld). /// /// For a mutex, this means that the [`lock`] and [`try_lock`] methods return a /// [`Result`] which indicates whether a mutex has been poisoned or not. Most /// usage of a mutex will simply [`unwrap()`] these results, propagating panics /// among threads to ensure that a possibly invalid invariant is not witnessed. /// /// A poisoned mutex, however, does not prevent all access to the underlying /// data. The [`PoisonError`] type has an [`into_inner`] method which will return /// the guard that would have otherwise been returned on a successful lock. This /// allows access to the data, despite the lock being poisoned. /// /// [`new`]: Self::new /// [`lock`]: Self::lock /// [`try_lock`]: Self::try_lock /// [`unwrap()`]: Result::unwrap /// [`PoisonError`]: super::PoisonError /// [`into_inner`]: super::PoisonError::into_inner /// /// # Examples /// /// ``` /// use std::sync::{Arc, Mutex}; /// use std::thread; /// use std::sync::mpsc::channel; /// /// const N: usize = 10; /// /// // Spawn a few threads to increment a shared variable (non-atomically), and /// // let the main thread know once all increments are done. /// // /// // Here we're using an Arc to share memory among threads, and the data inside /// // the Arc is protected with a mutex. /// let data = Arc::new(Mutex::new(0)); /// /// let (tx, rx) = channel(); /// for _ in 0..N { /// let (data, tx) = (Arc::clone(&data), tx.clone()); /// thread::spawn(move || { /// // The shared state can only be accessed once the lock is held. /// // Our non-atomic increment is safe because we're the only thread /// // which can access the shared state when the lock is held. /// // /// // We unwrap() the return value to assert that we are not expecting /// // threads to ever fail while holding the lock. /// let mut data = data.lock().unwrap(); /// *data += 1; /// if *data == N { /// tx.send(()).unwrap(); /// } /// // the lock is unlocked here when `data` goes out of scope. /// }); /// } /// /// rx.recv().unwrap(); /// ``` /// /// To recover from a poisoned mutex: /// /// ``` /// use std::sync::{Arc, Mutex}; /// use std::thread; /// /// let lock = Arc::new(Mutex::new(0_u32)); /// let lock2 = Arc::clone(&lock); /// /// let _ = thread::spawn(move || -> () { /// // This thread will acquire the mutex first, unwrapping the result of /// // `lock` because the lock has not been poisoned. /// let _guard = lock2.lock().unwrap(); /// /// // This panic while holding the lock (`_guard` is in scope) will poison /// // the mutex. /// panic!(); /// }).join(); /// /// // The lock is poisoned by this point, but the returned result can be /// // pattern matched on to return the underlying guard on both branches. /// let mut guard = match lock.lock() { /// Ok(guard) => guard, /// Err(poisoned) => poisoned.into_inner(), /// }; /// /// *guard += 1; /// ``` /// /// It is sometimes necessary to manually drop the mutex guard to unlock it /// sooner than the end of the enclosing scope. /// /// ``` /// use std::sync::{Arc, Mutex}; /// use std::thread; /// /// const N: usize = 3; /// /// let data_mutex = Arc::new(Mutex::new(vec![1, 2, 3, 4])); /// let res_mutex = Arc::new(Mutex::new(0)); /// /// let mut threads = Vec::with_capacity(N); /// (0..N).for_each(|_| { /// let data_mutex_clone = Arc::clone(&data_mutex); /// let res_mutex_clone = Arc::clone(&res_mutex); /// /// threads.push(thread::spawn(move || { /// let mut data = data_mutex_clone.lock().unwrap(); /// // This is the result of some important and long-ish work. /// let result = data.iter().fold(0, |acc, x| acc + x * 2); /// data.push(result); /// drop(data); /// *res_mutex_clone.lock().unwrap() += result; /// })); /// }); /// /// let mut data = data_mutex.lock().unwrap(); /// // This is the result of some important and long-ish work. /// let result = data.iter().fold(0, |acc, x| acc + x * 2); /// data.push(result); /// // We drop the `data` explicitly because it's not necessary anymore and the /// // thread still has work to do. This allow other threads to start working on /// // the data immediately, without waiting for the rest of the unrelated work /// // to be done here. /// // /// // It's even more important here than in the threads because we `.join` the /// // threads after that. If we had not dropped the mutex guard, a thread could /// // be waiting forever for it, causing a deadlock. /// drop(data); /// // Here the mutex guard is not assigned to a variable and so, even if the /// // scope does not end after this line, the mutex is still released: there is /// // no deadlock. /// *res_mutex.lock().unwrap() += result; /// /// threads.into_iter().for_each(|thread| { /// thread /// .join() /// .expect("The thread creating or execution failed !") /// }); /// /// assert_eq!(*res_mutex.lock().unwrap(), 800); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "Mutex")] pub struct Mutex { inner: sys::MovableMutex, poison: poison::Flag, data: UnsafeCell, } // these are the only places where `T: Send` matters; all other // functionality works fine on a single thread. #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for Mutex {} #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Sync for Mutex {} /// An RAII implementation of a "scoped lock" of a mutex. When this structure is /// dropped (falls out of scope), the lock will be unlocked. /// /// The data protected by the mutex can be accessed through this guard via its /// [`Deref`] and [`DerefMut`] implementations. /// /// This structure is created by the [`lock`] and [`try_lock`] methods on /// [`Mutex`]. /// /// [`lock`]: Mutex::lock /// [`try_lock`]: Mutex::try_lock #[must_use = "if unused the Mutex will immediately unlock"] #[must_not_suspend = "holding a MutexGuard across suspend \ points can cause deadlocks, delays, \ and cause Futures to not implement `Send`"] #[stable(feature = "rust1", since = "1.0.0")] #[clippy::has_significant_drop] pub struct MutexGuard<'a, T: ?Sized + 'a> { lock: &'a Mutex, poison: poison::Guard, } #[stable(feature = "rust1", since = "1.0.0")] impl !Send for MutexGuard<'_, T> {} #[stable(feature = "mutexguard", since = "1.19.0")] unsafe impl Sync for MutexGuard<'_, T> {} impl Mutex { /// Creates a new mutex in an unlocked state ready for use. /// /// # Examples /// /// ``` /// use std::sync::Mutex; /// /// let mutex = Mutex::new(0); /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] #[inline] pub const fn new(t: T) -> Mutex { Mutex { inner: sys::MovableMutex::new(), poison: poison::Flag::new(), data: UnsafeCell::new(t), } } } impl Mutex { /// Acquires a mutex, blocking the current thread until it is able to do so. /// /// This function will block the local thread until it is available to acquire /// the mutex. Upon returning, the thread is the only thread with the lock /// held. An RAII guard is returned to allow scoped unlock of the lock. When /// the guard goes out of scope, the mutex will be unlocked. /// /// The exact behavior on locking a mutex in the thread which already holds /// the lock is left unspecified. However, this function will not return on /// the second call (it might panic or deadlock, for example). /// /// # Errors /// /// If another user of this mutex panicked while holding the mutex, then /// this call will return an error once the mutex is acquired. /// /// # Panics /// /// This function might panic when called if the lock is already held by /// the current thread. /// /// # Examples /// /// ``` /// use std::sync::{Arc, Mutex}; /// use std::thread; /// /// let mutex = Arc::new(Mutex::new(0)); /// let c_mutex = Arc::clone(&mutex); /// /// thread::spawn(move || { /// *c_mutex.lock().unwrap() = 10; /// }).join().expect("thread::spawn failed"); /// assert_eq!(*mutex.lock().unwrap(), 10); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn lock(&self) -> LockResult> { unsafe { self.inner.raw_lock(); MutexGuard::new(self) } } /// Attempts to acquire this lock. /// /// If the lock could not be acquired at this time, then [`Err`] is returned. /// Otherwise, an RAII guard is returned. The lock will be unlocked when the /// guard is dropped. /// /// This function does not block. /// /// # Errors /// /// If another user of this mutex panicked while holding the mutex, then /// this call will return the [`Poisoned`] error if the mutex would /// otherwise be acquired. /// /// If the mutex could not be acquired because it is already locked, then /// this call will return the [`WouldBlock`] error. /// /// [`Poisoned`]: TryLockError::Poisoned /// [`WouldBlock`]: TryLockError::WouldBlock /// /// # Examples /// /// ``` /// use std::sync::{Arc, Mutex}; /// use std::thread; /// /// let mutex = Arc::new(Mutex::new(0)); /// let c_mutex = Arc::clone(&mutex); /// /// thread::spawn(move || { /// let mut lock = c_mutex.try_lock(); /// if let Ok(ref mut mutex) = lock { /// **mutex = 10; /// } else { /// println!("try_lock failed"); /// } /// }).join().expect("thread::spawn failed"); /// assert_eq!(*mutex.lock().unwrap(), 10); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn try_lock(&self) -> TryLockResult> { unsafe { if self.inner.try_lock() { Ok(MutexGuard::new(self)?) } else { Err(TryLockError::WouldBlock) } } } /// Immediately drops the guard, and consequently unlocks the mutex. /// /// This function is equivalent to calling [`drop`] on the guard but is more self-documenting. /// Alternately, the guard will be automatically dropped when it goes out of scope. /// /// ``` /// #![feature(mutex_unlock)] /// /// use std::sync::Mutex; /// let mutex = Mutex::new(0); /// /// let mut guard = mutex.lock().unwrap(); /// *guard += 20; /// Mutex::unlock(guard); /// ``` #[unstable(feature = "mutex_unlock", issue = "81872")] pub fn unlock(guard: MutexGuard<'_, T>) { drop(guard); } /// Determines whether the mutex is poisoned. /// /// If another thread is active, the mutex can still become poisoned at any /// time. You should not trust a `false` value for program correctness /// without additional synchronization. /// /// # Examples /// /// ``` /// use std::sync::{Arc, Mutex}; /// use std::thread; /// /// let mutex = Arc::new(Mutex::new(0)); /// let c_mutex = Arc::clone(&mutex); /// /// let _ = thread::spawn(move || { /// let _lock = c_mutex.lock().unwrap(); /// panic!(); // the mutex gets poisoned /// }).join(); /// assert_eq!(mutex.is_poisoned(), true); /// ``` #[inline] #[stable(feature = "sync_poison", since = "1.2.0")] pub fn is_poisoned(&self) -> bool { self.poison.get() } /// Clear the poisoned state from a mutex /// /// If the mutex is poisoned, it will remain poisoned until this function is called. This /// allows recovering from a poisoned state and marking that it has recovered. For example, if /// the value is overwritten by a known-good value, then the mutex can be marked as /// un-poisoned. Or possibly, the value could be inspected to determine if it is in a /// consistent state, and if so the poison is removed. /// /// # Examples /// /// ``` /// #![feature(mutex_unpoison)] /// /// use std::sync::{Arc, Mutex}; /// use std::thread; /// /// let mutex = Arc::new(Mutex::new(0)); /// let c_mutex = Arc::clone(&mutex); /// /// let _ = thread::spawn(move || { /// let _lock = c_mutex.lock().unwrap(); /// panic!(); // the mutex gets poisoned /// }).join(); /// /// assert_eq!(mutex.is_poisoned(), true); /// let x = mutex.lock().unwrap_or_else(|mut e| { /// **e.get_mut() = 1; /// mutex.clear_poison(); /// e.into_inner() /// }); /// assert_eq!(mutex.is_poisoned(), false); /// assert_eq!(*x, 1); /// ``` #[inline] #[unstable(feature = "mutex_unpoison", issue = "96469")] pub fn clear_poison(&self) { self.poison.clear(); } /// Consumes this mutex, returning the underlying data. /// /// # Errors /// /// If another user of this mutex panicked while holding the mutex, then /// this call will return an error instead. /// /// # Examples /// /// ``` /// use std::sync::Mutex; /// /// let mutex = Mutex::new(0); /// assert_eq!(mutex.into_inner().unwrap(), 0); /// ``` #[stable(feature = "mutex_into_inner", since = "1.6.0")] pub fn into_inner(self) -> LockResult where T: Sized, { let data = self.data.into_inner(); poison::map_result(self.poison.borrow(), |()| data) } /// Returns a mutable reference to the underlying data. /// /// Since this call borrows the `Mutex` mutably, no actual locking needs to /// take place -- the mutable borrow statically guarantees no locks exist. /// /// # Errors /// /// If another user of this mutex panicked while holding the mutex, then /// this call will return an error instead. /// /// # Examples /// /// ``` /// use std::sync::Mutex; /// /// let mut mutex = Mutex::new(0); /// *mutex.get_mut().unwrap() = 10; /// assert_eq!(*mutex.lock().unwrap(), 10); /// ``` #[stable(feature = "mutex_get_mut", since = "1.6.0")] pub fn get_mut(&mut self) -> LockResult<&mut T> { let data = self.data.get_mut(); poison::map_result(self.poison.borrow(), |()| data) } } #[stable(feature = "mutex_from", since = "1.24.0")] impl From for Mutex { /// Creates a new mutex in an unlocked state ready for use. /// This is equivalent to [`Mutex::new`]. fn from(t: T) -> Self { Mutex::new(t) } } #[stable(feature = "mutex_default", since = "1.10.0")] impl Default for Mutex { /// Creates a `Mutex`, with the `Default` value for T. fn default() -> Mutex { Mutex::new(Default::default()) } } #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Mutex { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut d = f.debug_struct("Mutex"); match self.try_lock() { Ok(guard) => { d.field("data", &&*guard); } Err(TryLockError::Poisoned(err)) => { d.field("data", &&**err.get_ref()); } Err(TryLockError::WouldBlock) => { struct LockedPlaceholder; impl fmt::Debug for LockedPlaceholder { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("") } } d.field("data", &LockedPlaceholder); } } d.field("poisoned", &self.poison.get()); d.finish_non_exhaustive() } } impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> { unsafe fn new(lock: &'mutex Mutex) -> LockResult> { poison::map_result(lock.poison.guard(), |guard| MutexGuard { lock, poison: guard }) } } #[stable(feature = "rust1", since = "1.0.0")] impl Deref for MutexGuard<'_, T> { type Target = T; fn deref(&self) -> &T { unsafe { &*self.lock.data.get() } } } #[stable(feature = "rust1", since = "1.0.0")] impl DerefMut for MutexGuard<'_, T> { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.lock.data.get() } } } #[stable(feature = "rust1", since = "1.0.0")] impl Drop for MutexGuard<'_, T> { #[inline] fn drop(&mut self) { unsafe { self.lock.poison.done(&self.poison); self.lock.inner.raw_unlock(); } } } #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for MutexGuard<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } #[stable(feature = "std_guard_impls", since = "1.20.0")] impl fmt::Display for MutexGuard<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) } } pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::MovableMutex { &guard.lock.inner } pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag { &guard.lock.poison }