]> git.proxmox.com Git - rustc.git/blobdiff - library/std/src/sync/mutex.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / library / std / src / sync / mutex.rs
index aacc893ba06468e6f7e2e54e125495c3b1cd4f0b..e0d13cd648c64ceeb003da18d1401e02104bccf2 100644 (file)
@@ -10,11 +10,10 @@ 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 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
 ///
@@ -214,7 +213,9 @@ impl<T> Mutex<T> {
     /// 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(),
@@ -364,6 +365,45 @@ impl<T: ?Sized> Mutex<T> {
         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
@@ -385,7 +425,7 @@ impl<T: ?Sized> Mutex<T> {
         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.
@@ -410,7 +450,7 @@ impl<T: ?Sized> Mutex<T> {
     #[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)
     }
 }
 
@@ -459,7 +499,7 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> {
 
 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 })
     }
 }