about summary refs log tree commit diff
path: root/src/libstd/sync
diff options
context:
space:
mode:
authorPankaj Chaudhary <pankajchaudhary172@gmail.com>2020-07-13 14:14:37 +0530
committerPankajChaudhary5 <pankajchaudhary172@gmail.com>2020-07-13 14:57:22 +0530
commitbc2b37aad7f9cbd1c97e416e6b16325b607422b8 (patch)
tree867a6176bcf763bba6e5de12bc08f034a320ac56 /src/libstd/sync
parente3ae4c7345cfd06b06c6996536d7c158ce6970db (diff)
parent9d09331e00b02f81c714b0c41ce3a38380dd36a2 (diff)
Merge branch 'master' into E0688
Diffstat (limited to 'src/libstd/sync')
-rw-r--r--src/libstd/sync/condvar.rs1
-rw-r--r--src/libstd/sync/mpsc/mod.rs3
-rw-r--r--src/libstd/sync/mpsc/shared.rs8
-rw-r--r--src/libstd/sync/mpsc/stream.rs2
-rw-r--r--src/libstd/sync/mpsc/sync.rs16
-rw-r--r--src/libstd/sync/mutex.rs55
-rw-r--r--src/libstd/sync/once.rs4
7 files changed, 72 insertions, 17 deletions
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index 77e521eae9a..2250c0d4203 100644
--- a/src/libstd/sync/condvar.rs
+++ b/src/libstd/sync/condvar.rs
@@ -609,7 +609,6 @@ mod tests {
     use crate::sync::{Arc, Condvar, Mutex};
     use crate::thread;
     use crate::time::Duration;
-    use crate::u64;
 
     #[test]
     fn smoke() {
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index e70204d6839..d6cc811154f 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -2176,8 +2176,7 @@ mod tests {
     #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31
     fn very_long_recv_timeout_wont_panic() {
         let (tx, rx) = channel::<()>();
-        let join_handle =
-            thread::spawn(move || rx.recv_timeout(Duration::from_secs(u64::max_value())));
+        let join_handle = thread::spawn(move || rx.recv_timeout(Duration::from_secs(u64::MAX)));
         thread::sleep(Duration::from_secs(1));
         assert!(tx.send(()).is_ok());
         assert_eq!(join_handle.join().unwrap(), Ok(()));
diff --git a/src/libstd/sync/mpsc/shared.rs b/src/libstd/sync/mpsc/shared.rs
index c4e929624d7..898654f21f2 100644
--- a/src/libstd/sync/mpsc/shared.rs
+++ b/src/libstd/sync/mpsc/shared.rs
@@ -91,7 +91,7 @@ impl<T> Packet<T> {
     //
     // This can only be called at channel-creation time
     pub fn inherit_blocker(&self, token: Option<SignalToken>, guard: MutexGuard<'_, ()>) {
-        token.map(|token| {
+        if let Some(token) = token {
             assert_eq!(self.cnt.load(Ordering::SeqCst), 0);
             assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
             self.to_wake.store(unsafe { token.cast_to_usize() }, Ordering::SeqCst);
@@ -118,7 +118,7 @@ impl<T> Packet<T> {
             unsafe {
                 *self.steals.get() = -1;
             }
-        });
+        }
 
         // When the shared packet is constructed, we grabbed this lock. The
         // purpose of this lock is to ensure that abort_selection() doesn't
@@ -354,9 +354,7 @@ impl<T> Packet<T> {
 
         // See comments on Arc::clone() on why we do this (for `mem::forget`).
         if old_count > MAX_REFCOUNT {
-            unsafe {
-                abort();
-            }
+            abort();
         }
     }
 
diff --git a/src/libstd/sync/mpsc/stream.rs b/src/libstd/sync/mpsc/stream.rs
index 26b4faebd86..9f7c1af8951 100644
--- a/src/libstd/sync/mpsc/stream.rs
+++ b/src/libstd/sync/mpsc/stream.rs
@@ -329,7 +329,7 @@ impl<T> Packet<T> {
             );
             cnt != DISCONNECTED && cnt != steals
         } {
-            while let Some(_) = self.queue.pop() {
+            while self.queue.pop().is_some() {
                 steals += 1;
             }
         }
diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs
index 3e2050799cc..733761671a0 100644
--- a/src/libstd/sync/mpsc/sync.rs
+++ b/src/libstd/sync/mpsc/sync.rs
@@ -343,8 +343,12 @@ impl<T> Packet<T> {
         mem::drop(guard);
 
         // only outside of the lock do we wake up the pending threads
-        pending_sender1.map(|t| t.signal());
-        pending_sender2.map(|t| t.signal());
+        if let Some(token) = pending_sender1 {
+            token.signal();
+        }
+        if let Some(token) = pending_sender2 {
+            token.signal();
+        }
     }
 
     // Prepares this shared packet for a channel clone, essentially just bumping
@@ -354,9 +358,7 @@ impl<T> Packet<T> {
 
         // See comments on Arc::clone() on why we do this (for `mem::forget`).
         if old_count > MAX_REFCOUNT {
-            unsafe {
-                abort();
-            }
+            abort();
         }
     }
 
@@ -410,7 +412,9 @@ impl<T> Packet<T> {
         while let Some(token) = queue.dequeue() {
             token.signal();
         }
-        waiter.map(|t| t.signal());
+        if let Some(token) = waiter {
+            token.signal();
+        }
     }
 }
 
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 0cb16b19d73..8478457eabf 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -107,7 +107,62 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
 ///
 /// *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_type")]
 pub struct Mutex<T: ?Sized> {
     // 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
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index 1e6b6c430be..7dc822db3d0 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -272,7 +272,7 @@ impl Once {
     /// result in an immediate panic. If `f` panics, the `Once` will remain
     /// in a poison state. If `f` does _not_ panic, the `Once` will no
     /// longer be in a poison state and all future calls to `call_once` or
-    /// `call_one_force` will be no-ops.
+    /// `call_once_force` will be no-ops.
     ///
     /// The closure `f` is yielded a [`OnceState`] structure which can be used
     /// to query the poison status of the `Once`.
@@ -497,7 +497,7 @@ impl Drop for WaiterQueue<'_> {
             let mut queue = (state_and_queue & !STATE_MASK) as *const Waiter;
             while !queue.is_null() {
                 let next = (*queue).next;
-                let thread = (*queue).thread.replace(None).unwrap();
+                let thread = (*queue).thread.take().unwrap();
                 (*queue).signaled.store(true, Ordering::Release);
                 // ^- FIXME (maybe): This is another case of issue #55005
                 // `store()` has a potentially dangling ref to `signaled`.