diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs index aacc893ba06..3d8281fe593 100644 --- a/library/std/src/sync/mutex.rs +++ b/library/std/src/sync/mutex.rs @@ -364,6 +364,45 @@ impl Mutex { 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 diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs index 07a90da449c..ba91fb0499f 100644 --- a/library/std/src/sync/poison.rs +++ b/library/std/src/sync/poison.rs @@ -40,6 +40,11 @@ impl Flag { pub fn get(&self) -> bool { self.failed.load(Ordering::Relaxed) } + + #[inline] + pub fn clear(&self) { + self.failed.store(false, Ordering::Relaxed) + } } pub struct Guard { diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs index 9ec0903f037..4f1b4bedaab 100644 --- a/library/std/src/sync/rwlock.rs +++ b/library/std/src/sync/rwlock.rs @@ -368,6 +368,45 @@ impl RwLock { self.poison.get() } + /// Clear the poisoned state from a lock + /// + /// If the lock 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, RwLock}; + /// use std::thread; + /// + /// let lock = Arc::new(RwLock::new(0)); + /// let c_lock = Arc::clone(&lock); + /// + /// let _ = thread::spawn(move || { + /// let _lock = c_lock.write().unwrap(); + /// panic!(); // the mutex gets poisoned + /// }).join(); + /// + /// assert_eq!(lock.is_poisoned(), true); + /// let guard = lock.write().unwrap_or_else(|mut e| { + /// **e.get_mut() = 1; + /// lock.clear_poison(); + /// e.into_inner() + /// }); + /// assert_eq!(lock.is_poisoned(), false); + /// assert_eq!(*guard, 1); + /// ``` + #[inline] + #[unstable(feature = "mutex_unpoison", issue = "96469")] + pub fn clear_poison(&self) { + self.poison.clear(); + } + /// Consumes this `RwLock`, returning the underlying data. /// /// # Errors