diff options
| author | Pankaj Chaudhary <pankajchaudhary172@gmail.com> | 2020-07-13 14:14:37 +0530 |
|---|---|---|
| committer | PankajChaudhary5 <pankajchaudhary172@gmail.com> | 2020-07-13 14:57:22 +0530 |
| commit | bc2b37aad7f9cbd1c97e416e6b16325b607422b8 (patch) | |
| tree | 867a6176bcf763bba6e5de12bc08f034a320ac56 /src/libstd/sync | |
| parent | e3ae4c7345cfd06b06c6996536d7c158ce6970db (diff) | |
| parent | 9d09331e00b02f81c714b0c41ce3a38380dd36a2 (diff) | |
Merge branch 'master' into E0688
Diffstat (limited to 'src/libstd/sync')
| -rw-r--r-- | src/libstd/sync/condvar.rs | 1 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/mod.rs | 3 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/shared.rs | 8 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/stream.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/sync.rs | 16 | ||||
| -rw-r--r-- | src/libstd/sync/mutex.rs | 55 | ||||
| -rw-r--r-- | src/libstd/sync/once.rs | 4 |
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`. |
