/// 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.
+/// 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
///
/// let mutex = Mutex::new(0);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn new(t: T) -> Mutex<T> {
+ #[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
+ #[inline]
+ pub const fn new(t: T) -> Mutex<T> {
Mutex {
inner: sys::MovableMutex::new(),
poison: poison::Flag::new(),
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
T: Sized,
{
let data = self.data.into_inner();
- poison::map_result(self.poison.borrow(), |_| data)
+ poison::map_result(self.poison.borrow(), |()| data)
}
/// Returns a mutable reference to the underlying data.
#[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)
+ poison::map_result(self.poison.borrow(), |()| data)
}
}
impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> {
unsafe fn new(lock: &'mutex Mutex<T>) -> LockResult<MutexGuard<'mutex, T>> {
- poison::map_result(lock.poison.borrow(), |guard| MutexGuard { lock, poison: guard })
+ poison::map_result(lock.poison.guard(), |guard| MutexGuard { lock, poison: guard })
}
}