use crate::cell::UnsafeCell; use crate::fmt; use crate::mem; use crate::ops::{Deref, DerefMut}; use crate::ptr; use crate::sys_common::mutex as sys; use crate::sys_common::poison::{self, TryLockError, TryLockResult, LockResult}; /// A mutual exclusion primitive useful for protecting shared data /// /// This mutex will block threads waiting for the lock to become available. The /// mutex can also be statically initialized or 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`]: #method.new /// [`lock`]: #method.lock /// [`try_lock`]: #method.try_lock /// [`Result`]: ../../std/result/enum.Result.html /// [`unwrap()`]: ../../std/result/enum.Result.html#method.unwrap /// [`PoisonError`]: ../../std/sync/struct.PoisonError.html /// [`into_inner`]: ../../std/sync/struct.PoisonError.html#method.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 = lock.clone(); /// /// 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; /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub struct Mutex { // Note that this mutex is in a *box*, not inlined into the struct itself. // Once a native mutex has been used once, its address can never change (it // can't be moved). This mutex type can be safely moved at any time, so to // ensure that the native mutex is used correctly we box the inner mutex to // give it a constant address. inner: Box, 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`]. /// /// [`Deref`]: ../../std/ops/trait.Deref.html /// [`DerefMut`]: ../../std/ops/trait.DerefMut.html /// [`lock`]: struct.Mutex.html#method.lock /// [`try_lock`]: struct.Mutex.html#method.try_lock /// [`Mutex`]: struct.Mutex.html #[must_use = "if unused the Mutex will immediately unlock"] #[stable(feature = "rust1", since = "1.0.0")] pub struct MutexGuard<'a, T: ?Sized + 'a> { // funny underscores due to how Deref/DerefMut currently work (they // disregard field privacy). __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")] pub fn new(t: T) -> Mutex { let mut m = Mutex { inner: box sys::Mutex::new(), poison: poison::Flag::new(), data: UnsafeCell::new(t), }; unsafe { m.inner.init(); } m } } 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 = mutex.clone(); /// /// 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 failure if the mutex would otherwise be /// acquired. /// /// [`Err`]: ../../std/result/enum.Result.html#variant.Err /// /// # Examples /// /// ``` /// use std::sync::{Arc, Mutex}; /// use std::thread; /// /// let mutex = Arc::new(Mutex::new(0)); /// let c_mutex = mutex.clone(); /// /// 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) } } } /// 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 = mutex.clone(); /// /// 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() } /// 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 { // We know statically that there are no outstanding references to // `self` so there's no need to lock the inner mutex. // // To get the inner value, we'd like to call `data.into_inner()`, // but because `Mutex` impl-s `Drop`, we can't move out of it, so // we'll have to destructure it manually instead. unsafe { // Like `let Mutex { inner, poison, data } = self`. let (inner, poison, data) = { let Mutex { ref inner, ref poison, ref data } = self; (ptr::read(inner), ptr::read(poison), ptr::read(data)) }; mem::forget(self); inner.destroy(); // Keep in sync with the `Drop` impl. drop(inner); poison::map_result(poison.borrow(), |_| data.into_inner()) } } /// 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> { // We know statically that there are no other references to `self`, so // there's no need to lock the inner mutex. let data = unsafe { &mut *self.data.get() }; poison::map_result(self.poison.borrow(), |_| data ) } } #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<#[may_dangle] T: ?Sized> Drop for Mutex { fn drop(&mut self) { // This is actually safe b/c we know that there is no further usage of // this mutex (it's up to the user to arrange for a mutex to get // dropped, that's not our job) // // IMPORTANT: This code must be kept in sync with `Mutex::into_inner`. unsafe { self.inner.destroy() } } } #[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`]. /// /// [`Mutex::new`]: ../../std/sync/struct.Mutex.html#method.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 { match self.try_lock() { Ok(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(), Err(TryLockError::Poisoned(err)) => { f.debug_struct("Mutex").field("data", &&**err.get_ref()).finish() }, Err(TryLockError::WouldBlock) => { struct LockedPlaceholder; impl fmt::Debug for LockedPlaceholder { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("") } } f.debug_struct("Mutex").field("data", &LockedPlaceholder).finish() } } } } impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> { unsafe fn new(lock: &'mutex Mutex) -> LockResult> { poison::map_result(lock.poison.borrow(), |guard| { MutexGuard { __lock: 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::Mutex { &guard.__lock.inner } pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag { &guard.__lock.poison } #[cfg(all(test, not(target_os = "emscripten")))] mod tests { use crate::sync::mpsc::channel; use crate::sync::{Arc, Mutex, Condvar}; use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::thread; struct Packet(Arc<(Mutex, Condvar)>); #[derive(Eq, PartialEq, Debug)] struct NonCopy(i32); #[test] fn smoke() { let m = Mutex::new(()); drop(m.lock().unwrap()); drop(m.lock().unwrap()); } #[test] fn lots_and_lots() { const J: u32 = 1000; const K: u32 = 3; let m = Arc::new(Mutex::new(0)); fn inc(m: &Mutex) { for _ in 0..J { *m.lock().unwrap() += 1; } } let (tx, rx) = channel(); for _ in 0..K { let tx2 = tx.clone(); let m2 = m.clone(); thread::spawn(move|| { inc(&m2); tx2.send(()).unwrap(); }); let tx2 = tx.clone(); let m2 = m.clone(); thread::spawn(move|| { inc(&m2); tx2.send(()).unwrap(); }); } drop(tx); for _ in 0..2 * K { rx.recv().unwrap(); } assert_eq!(*m.lock().unwrap(), J * K * 2); } #[test] fn try_lock() { let m = Mutex::new(()); *m.try_lock().unwrap() = (); } #[test] fn test_into_inner() { let m = Mutex::new(NonCopy(10)); assert_eq!(m.into_inner().unwrap(), NonCopy(10)); } #[test] fn test_into_inner_drop() { struct Foo(Arc); impl Drop for Foo { fn drop(&mut self) { self.0.fetch_add(1, Ordering::SeqCst); } } let num_drops = Arc::new(AtomicUsize::new(0)); let m = Mutex::new(Foo(num_drops.clone())); assert_eq!(num_drops.load(Ordering::SeqCst), 0); { let _inner = m.into_inner().unwrap(); assert_eq!(num_drops.load(Ordering::SeqCst), 0); } assert_eq!(num_drops.load(Ordering::SeqCst), 1); } #[test] fn test_into_inner_poison() { let m = Arc::new(Mutex::new(NonCopy(10))); let m2 = m.clone(); let _ = thread::spawn(move || { let _lock = m2.lock().unwrap(); panic!("test panic in inner thread to poison mutex"); }).join(); assert!(m.is_poisoned()); match Arc::try_unwrap(m).unwrap().into_inner() { Err(e) => assert_eq!(e.into_inner(), NonCopy(10)), Ok(x) => panic!("into_inner of poisoned Mutex is Ok: {:?}", x), } } #[test] fn test_get_mut() { let mut m = Mutex::new(NonCopy(10)); *m.get_mut().unwrap() = NonCopy(20); assert_eq!(m.into_inner().unwrap(), NonCopy(20)); } #[test] fn test_get_mut_poison() { let m = Arc::new(Mutex::new(NonCopy(10))); let m2 = m.clone(); let _ = thread::spawn(move || { let _lock = m2.lock().unwrap(); panic!("test panic in inner thread to poison mutex"); }).join(); assert!(m.is_poisoned()); match Arc::try_unwrap(m).unwrap().get_mut() { Err(e) => assert_eq!(*e.into_inner(), NonCopy(10)), Ok(x) => panic!("get_mut of poisoned Mutex is Ok: {:?}", x), } } #[test] fn test_mutex_arc_condvar() { let packet = Packet(Arc::new((Mutex::new(false), Condvar::new()))); let packet2 = Packet(packet.0.clone()); let (tx, rx) = channel(); let _t = thread::spawn(move|| { // wait until parent gets in rx.recv().unwrap(); let &(ref lock, ref cvar) = &*packet2.0; let mut lock = lock.lock().unwrap(); *lock = true; cvar.notify_one(); }); let &(ref lock, ref cvar) = &*packet.0; let mut lock = lock.lock().unwrap(); tx.send(()).unwrap(); assert!(!*lock); while !*lock { lock = cvar.wait(lock).unwrap(); } } #[test] fn test_arc_condvar_poison() { let packet = Packet(Arc::new((Mutex::new(1), Condvar::new()))); let packet2 = Packet(packet.0.clone()); let (tx, rx) = channel(); let _t = thread::spawn(move || -> () { rx.recv().unwrap(); let &(ref lock, ref cvar) = &*packet2.0; let _g = lock.lock().unwrap(); cvar.notify_one(); // Parent should fail when it wakes up. panic!(); }); let &(ref lock, ref cvar) = &*packet.0; let mut lock = lock.lock().unwrap(); tx.send(()).unwrap(); while *lock == 1 { match cvar.wait(lock) { Ok(l) => { lock = l; assert_eq!(*lock, 1); } Err(..) => break, } } } #[test] fn test_mutex_arc_poison() { let arc = Arc::new(Mutex::new(1)); assert!(!arc.is_poisoned()); let arc2 = arc.clone(); let _ = thread::spawn(move|| { let lock = arc2.lock().unwrap(); assert_eq!(*lock, 2); }).join(); assert!(arc.lock().is_err()); assert!(arc.is_poisoned()); } #[test] fn test_mutex_arc_nested() { // Tests nested mutexes and access // to underlying data. let arc = Arc::new(Mutex::new(1)); let arc2 = Arc::new(Mutex::new(arc)); let (tx, rx) = channel(); let _t = thread::spawn(move|| { let lock = arc2.lock().unwrap(); let lock2 = lock.lock().unwrap(); assert_eq!(*lock2, 1); tx.send(()).unwrap(); }); rx.recv().unwrap(); } #[test] fn test_mutex_arc_access_in_unwind() { let arc = Arc::new(Mutex::new(1)); let arc2 = arc.clone(); let _ = thread::spawn(move|| -> () { struct Unwinder { i: Arc>, } impl Drop for Unwinder { fn drop(&mut self) { *self.i.lock().unwrap() += 1; } } let _u = Unwinder { i: arc2 }; panic!(); }).join(); let lock = arc.lock().unwrap(); assert_eq!(*lock, 2); } #[test] fn test_mutex_unsized() { let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]); { let b = &mut *mutex.lock().unwrap(); b[0] = 4; b[2] = 5; } let comp: &[i32] = &[4, 2, 5]; assert_eq!(&*mutex.lock().unwrap(), comp); } }