diff options
| author | Sayan Nandan <17377258+sntdevco@users.noreply.github.com> | 2019-08-09 13:01:05 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-08-09 13:01:05 +0530 |
| commit | fb3a01354ffecc41d7a189e4dd225d706387a522 (patch) | |
| tree | 41492dfe93f1dccba847dadb56ac6aa079edaaa9 /src/libstd/sync | |
| parent | 33445aea509cadcd715009c79795d289268daa7c (diff) | |
| parent | 5aa3d9a7b5d3a46a7f158e8881146331a6bc9243 (diff) | |
| download | rust-fb3a01354ffecc41d7a189e4dd225d706387a522.tar.gz rust-fb3a01354ffecc41d7a189e4dd225d706387a522.zip | |
Merge pull request #1 from rust-lang/master
Merge recent changes into master
Diffstat (limited to 'src/libstd/sync')
| -rw-r--r-- | src/libstd/sync/barrier.rs | 4 | ||||
| -rw-r--r-- | src/libstd/sync/condvar.rs | 54 | ||||
| -rw-r--r-- | src/libstd/sync/mod.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/mod.rs | 136 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/oneshot.rs | 72 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/select.rs | 352 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/select_tests.rs | 413 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/shared.rs | 39 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/stream.rs | 53 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/sync.rs | 61 | ||||
| -rw-r--r-- | src/libstd/sync/mutex.rs | 16 | ||||
| -rw-r--r-- | src/libstd/sync/once.rs | 7 | ||||
| -rw-r--r-- | src/libstd/sync/rwlock.rs | 24 |
13 files changed, 117 insertions, 1116 deletions
diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index a4205daba8b..23ba63a6109 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -59,7 +59,7 @@ pub struct BarrierWaitResult(bool); #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Barrier { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad("Barrier { .. }") } } @@ -151,7 +151,7 @@ impl Barrier { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for BarrierWaitResult { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("BarrierWaitResult") .field("is_leader", &self.is_leader()) .finish() diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 5ebb61754e1..aeff57716e8 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -36,7 +36,7 @@ impl WaitTimeoutResult { /// let pair2 = pair.clone(); /// /// thread::spawn(move|| { - /// let &(ref lock, ref cvar) = &*pair2; + /// let (lock, cvar) = &*pair2; /// /// // Let's wait 20 milliseconds before notifying the condvar. /// thread::sleep(Duration::from_millis(20)); @@ -48,7 +48,7 @@ impl WaitTimeoutResult { /// }); /// /// // Wait for the thread to start up. - /// let &(ref lock, ref cvar) = &*pair; + /// let (lock, cvar) = &*pair; /// let mut started = lock.lock().unwrap(); /// loop { /// // Let's put a timeout on the condvar's wait. @@ -94,7 +94,7 @@ impl WaitTimeoutResult { /// /// // Inside of our lock, spawn a new thread, and then wait for it to start. /// thread::spawn(move|| { -/// let &(ref lock, ref cvar) = &*pair2; +/// let (lock, cvar) = &*pair2; /// let mut started = lock.lock().unwrap(); /// *started = true; /// // We notify the condvar that the value has changed. @@ -102,7 +102,7 @@ impl WaitTimeoutResult { /// }); /// /// // Wait for the thread to start up. -/// let &(ref lock, ref cvar) = &*pair; +/// let (lock, cvar) = &*pair; /// let mut started = lock.lock().unwrap(); /// while !*started { /// started = cvar.wait(started).unwrap(); @@ -180,7 +180,7 @@ impl Condvar { /// let pair2 = pair.clone(); /// /// thread::spawn(move|| { - /// let &(ref lock, ref cvar) = &*pair2; + /// let (lock, cvar) = &*pair2; /// let mut started = lock.lock().unwrap(); /// *started = true; /// // We notify the condvar that the value has changed. @@ -188,9 +188,9 @@ impl Condvar { /// }); /// /// // Wait for the thread to start up. - /// let &(ref lock, ref cvar) = &*pair; + /// let (lock, cvar) = &*pair; /// let mut started = lock.lock().unwrap(); - /// // As long as the value inside the `Mutex` is false, we wait. + /// // As long as the value inside the `Mutex<bool>` is `false`, we wait. /// while !*started { /// started = cvar.wait(started).unwrap(); /// } @@ -245,7 +245,7 @@ impl Condvar { /// let pair2 = pair.clone(); /// /// thread::spawn(move|| { - /// let &(ref lock, ref cvar) = &*pair2; + /// let (lock, cvar) = &*pair2; /// let mut started = lock.lock().unwrap(); /// *started = true; /// // We notify the condvar that the value has changed. @@ -253,8 +253,8 @@ impl Condvar { /// }); /// /// // Wait for the thread to start up. - /// let &(ref lock, ref cvar) = &*pair; - /// // As long as the value inside the `Mutex` is false, we wait. + /// let (lock, cvar) = &*pair; + /// // As long as the value inside the `Mutex<bool>` is `false`, we wait. /// let _guard = cvar.wait_until(lock.lock().unwrap(), |started| { *started }).unwrap(); /// ``` #[unstable(feature = "wait_until", issue = "47960")] @@ -301,7 +301,7 @@ impl Condvar { /// let pair2 = pair.clone(); /// /// thread::spawn(move|| { - /// let &(ref lock, ref cvar) = &*pair2; + /// let (lock, cvar) = &*pair2; /// let mut started = lock.lock().unwrap(); /// *started = true; /// // We notify the condvar that the value has changed. @@ -309,9 +309,9 @@ impl Condvar { /// }); /// /// // Wait for the thread to start up. - /// let &(ref lock, ref cvar) = &*pair; + /// let (lock, cvar) = &*pair; /// let mut started = lock.lock().unwrap(); - /// // As long as the value inside the `Mutex` is false, we wait. + /// // As long as the value inside the `Mutex<bool>` is `false`, we wait. /// loop { /// let result = cvar.wait_timeout_ms(started, 10).unwrap(); /// // 10 milliseconds have passed, or maybe the value changed! @@ -374,7 +374,7 @@ impl Condvar { /// let pair2 = pair.clone(); /// /// thread::spawn(move|| { - /// let &(ref lock, ref cvar) = &*pair2; + /// let (lock, cvar) = &*pair2; /// let mut started = lock.lock().unwrap(); /// *started = true; /// // We notify the condvar that the value has changed. @@ -382,9 +382,9 @@ impl Condvar { /// }); /// /// // wait for the thread to start up - /// let &(ref lock, ref cvar) = &*pair; + /// let (lock, cvar) = &*pair; /// let mut started = lock.lock().unwrap(); - /// // as long as the value inside the `Mutex` is false, we wait + /// // as long as the value inside the `Mutex<bool>` is `false`, we wait /// loop { /// let result = cvar.wait_timeout(started, Duration::from_millis(10)).unwrap(); /// // 10 milliseconds have passed, or maybe the value changed! @@ -449,7 +449,7 @@ impl Condvar { /// let pair2 = pair.clone(); /// /// thread::spawn(move|| { - /// let &(ref lock, ref cvar) = &*pair2; + /// let (lock, cvar) = &*pair2; /// let mut started = lock.lock().unwrap(); /// *started = true; /// // We notify the condvar that the value has changed. @@ -457,7 +457,7 @@ impl Condvar { /// }); /// /// // wait for the thread to start up - /// let &(ref lock, ref cvar) = &*pair; + /// let (lock, cvar) = &*pair; /// let result = cvar.wait_timeout_until( /// lock.lock().unwrap(), /// Duration::from_millis(100), @@ -508,7 +508,7 @@ impl Condvar { /// let pair2 = pair.clone(); /// /// thread::spawn(move|| { - /// let &(ref lock, ref cvar) = &*pair2; + /// let (lock, cvar) = &*pair2; /// let mut started = lock.lock().unwrap(); /// *started = true; /// // We notify the condvar that the value has changed. @@ -516,9 +516,9 @@ impl Condvar { /// }); /// /// // Wait for the thread to start up. - /// let &(ref lock, ref cvar) = &*pair; + /// let (lock, cvar) = &*pair; /// let mut started = lock.lock().unwrap(); - /// // As long as the value inside the `Mutex` is false, we wait. + /// // As long as the value inside the `Mutex<bool>` is `false`, we wait. /// while !*started { /// started = cvar.wait(started).unwrap(); /// } @@ -548,7 +548,7 @@ impl Condvar { /// let pair2 = pair.clone(); /// /// thread::spawn(move|| { - /// let &(ref lock, ref cvar) = &*pair2; + /// let (lock, cvar) = &*pair2; /// let mut started = lock.lock().unwrap(); /// *started = true; /// // We notify the condvar that the value has changed. @@ -556,9 +556,9 @@ impl Condvar { /// }); /// /// // Wait for the thread to start up. - /// let &(ref lock, ref cvar) = &*pair; + /// let (lock, cvar) = &*pair; /// let mut started = lock.lock().unwrap(); - /// // As long as the value inside the `Mutex` is false, we wait. + /// // As long as the value inside the `Mutex<bool>` is `false`, we wait. /// while !*started { /// started = cvar.wait(started).unwrap(); /// } @@ -589,7 +589,7 @@ impl Condvar { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Condvar { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad("Condvar { .. }") } } @@ -705,6 +705,7 @@ mod tests { #[test] #[cfg_attr(target_os = "emscripten", ignore)] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn wait_timeout_wait() { let m = Arc::new(Mutex::new(())); let c = Arc::new(Condvar::new()); @@ -724,6 +725,7 @@ mod tests { #[test] #[cfg_attr(target_os = "emscripten", ignore)] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn wait_timeout_until_wait() { let m = Arc::new(Mutex::new(())); let c = Arc::new(Condvar::new()); @@ -748,6 +750,7 @@ mod tests { #[test] #[cfg_attr(target_os = "emscripten", ignore)] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn wait_timeout_until_wake() { let pair = Arc::new((Mutex::new(false), Condvar::new())); let pair_copy = pair.clone(); @@ -771,6 +774,7 @@ mod tests { #[test] #[cfg_attr(target_os = "emscripten", ignore)] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn wait_timeout_wake() { let m = Arc::new(Mutex::new(())); let c = Arc::new(Condvar::new()); diff --git a/src/libstd/sync/mod.rs b/src/libstd/sync/mod.rs index 809ee882698..e29faf18d83 100644 --- a/src/libstd/sync/mod.rs +++ b/src/libstd/sync/mod.rs @@ -163,6 +163,8 @@ pub use self::condvar::{Condvar, WaitTimeoutResult}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::mutex::{Mutex, MutexGuard}; #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(bootstrap, allow(deprecated_in_future))] +#[allow(deprecated)] pub use self::once::{Once, OnceState, ONCE_INIT}; #[stable(feature = "rust1", since = "1.0.0")] pub use crate::sys_common::poison::{PoisonError, TryLockError, TryLockResult, LockResult}; diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 90c5c50c23b..69ecd201063 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -1,3 +1,5 @@ +// ignore-tidy-filelength + //! Multi-producer, single-consumer FIFO queue communication primitives. //! //! This module provides message-based communication over channels, concretely @@ -114,7 +116,6 @@ //! ``` #![stable(feature = "rust1", since = "1.0.0")] -#![allow(deprecated)] // for mpsc_select // A description of how Rust's channel implementation works // @@ -261,6 +262,8 @@ // believe that there is anything fundamental that needs to change about these // channels, however, in order to support a more efficient select(). // +// FIXME: Select is now removed, so these factors are ready to be cleaned up! +// // # Conclusion // // And now that you've seen all the races that I found and attempted to fix, @@ -273,18 +276,8 @@ use crate::mem; use crate::cell::UnsafeCell; use crate::time::{Duration, Instant}; -#[unstable(feature = "mpsc_select", issue = "27800")] -pub use self::select::{Select, Handle}; -use self::select::StartResult; -use self::select::StartResult::*; -use self::blocking::SignalToken; - -#[cfg(all(test, not(target_os = "emscripten")))] -mod select_tests; - mod blocking; mod oneshot; -mod select; mod shared; mod stream; mod sync; @@ -914,7 +907,7 @@ impl<T> Drop for Sender<T> { #[stable(feature = "mpsc_debug", since = "1.8.0")] impl<T> fmt::Debug for Sender<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Sender").finish() } } @@ -1005,7 +998,7 @@ impl<T> SyncSender<T> { /// thread::spawn(move || { /// // This will return an error and send /// // no message if the buffer is full - /// sync_sender2.try_send(3).is_err(); + /// let _ = sync_sender2.try_send(3); /// }); /// /// let mut msg; @@ -1044,7 +1037,7 @@ impl<T> Drop for SyncSender<T> { #[stable(feature = "mpsc_debug", since = "1.8.0")] impl<T> fmt::Debug for SyncSender<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SyncSender").finish() } } @@ -1463,7 +1456,7 @@ impl<T> Receiver<T> { /// assert_eq!(iter.next(), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn iter(&self) -> Iter<T> { + pub fn iter(&self) -> Iter<'_, T> { Iter { rx: self } } @@ -1506,84 +1499,12 @@ impl<T> Receiver<T> { /// assert_eq!(iter.next(), None); /// ``` #[stable(feature = "receiver_try_iter", since = "1.15.0")] - pub fn try_iter(&self) -> TryIter<T> { + pub fn try_iter(&self) -> TryIter<'_, T> { TryIter { rx: self } } } -impl<T> select::Packet for Receiver<T> { - fn can_recv(&self) -> bool { - loop { - let new_port = match *unsafe { self.inner() } { - Flavor::Oneshot(ref p) => { - match p.can_recv() { - Ok(ret) => return ret, - Err(upgrade) => upgrade, - } - } - Flavor::Stream(ref p) => { - match p.can_recv() { - Ok(ret) => return ret, - Err(upgrade) => upgrade, - } - } - Flavor::Shared(ref p) => return p.can_recv(), - Flavor::Sync(ref p) => return p.can_recv(), - }; - unsafe { - mem::swap(self.inner_mut(), - new_port.inner_mut()); - } - } - } - - fn start_selection(&self, mut token: SignalToken) -> StartResult { - loop { - let (t, new_port) = match *unsafe { self.inner() } { - Flavor::Oneshot(ref p) => { - match p.start_selection(token) { - oneshot::SelSuccess => return Installed, - oneshot::SelCanceled => return Abort, - oneshot::SelUpgraded(t, rx) => (t, rx), - } - } - Flavor::Stream(ref p) => { - match p.start_selection(token) { - stream::SelSuccess => return Installed, - stream::SelCanceled => return Abort, - stream::SelUpgraded(t, rx) => (t, rx), - } - } - Flavor::Shared(ref p) => return p.start_selection(token), - Flavor::Sync(ref p) => return p.start_selection(token), - }; - token = t; - unsafe { - mem::swap(self.inner_mut(), new_port.inner_mut()); - } - } - } - - fn abort_selection(&self) -> bool { - let mut was_upgrade = false; - loop { - let result = match *unsafe { self.inner() } { - Flavor::Oneshot(ref p) => p.abort_selection(), - Flavor::Stream(ref p) => p.abort_selection(was_upgrade), - Flavor::Shared(ref p) => return p.abort_selection(was_upgrade), - Flavor::Sync(ref p) => return p.abort_selection(), - }; - let new_port = match result { Ok(b) => return b, Err(p) => p }; - was_upgrade = true; - unsafe { - mem::swap(self.inner_mut(), - new_port.inner_mut()); - } - } - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Iterator for Iter<'a, T> { type Item = T; @@ -1636,21 +1557,21 @@ impl<T> Drop for Receiver<T> { #[stable(feature = "mpsc_debug", since = "1.8.0")] impl<T> fmt::Debug for Receiver<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Receiver").finish() } } #[stable(feature = "rust1", since = "1.0.0")] impl<T> fmt::Debug for SendError<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { "SendError(..)".fmt(f) } } #[stable(feature = "rust1", since = "1.0.0")] impl<T> fmt::Display for SendError<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { "sending on a closed channel".fmt(f) } } @@ -1668,7 +1589,7 @@ impl<T: Send> error::Error for SendError<T> { #[stable(feature = "rust1", since = "1.0.0")] impl<T> fmt::Debug for TrySendError<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { TrySendError::Full(..) => "Full(..)".fmt(f), TrySendError::Disconnected(..) => "Disconnected(..)".fmt(f), @@ -1678,7 +1599,7 @@ impl<T> fmt::Debug for TrySendError<T> { #[stable(feature = "rust1", since = "1.0.0")] impl<T> fmt::Display for TrySendError<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { TrySendError::Full(..) => { "sending on a full channel".fmt(f) @@ -1720,7 +1641,7 @@ impl<T> From<SendError<T>> for TrySendError<T> { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for RecvError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { "receiving on a closed channel".fmt(f) } } @@ -1739,7 +1660,7 @@ impl error::Error for RecvError { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for TryRecvError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { TryRecvError::Empty => { "receiving on an empty channel".fmt(f) @@ -1781,7 +1702,7 @@ impl From<RecvError> for TryRecvError { #[stable(feature = "mpsc_recv_timeout_error", since = "1.15.0")] impl fmt::Display for RecvTimeoutError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { RecvTimeoutError::Timeout => { "timed out waiting on channel".fmt(f) @@ -1951,7 +1872,7 @@ mod tests { for _ in 0..10000 { assert_eq!(rx.recv().unwrap(), 1); } - t.join().ok().unwrap(); + t.join().ok().expect("thread panicked"); } #[test] @@ -1977,7 +1898,7 @@ mod tests { }); } drop(tx); - t.join().ok().unwrap(); + t.join().ok().expect("thread panicked"); } #[test] @@ -1996,8 +1917,8 @@ mod tests { tx2.send(1).unwrap(); } }); - t1.join().ok().unwrap(); - t2.join().ok().unwrap(); + t1.join().ok().expect("thread panicked"); + t2.join().ok().expect("thread panicked"); } #[test] @@ -2011,7 +1932,7 @@ mod tests { for _ in 0..40 { tx.send(1).unwrap(); } - t.join().ok().unwrap(); + t.join().ok().expect("thread panicked"); } #[test] @@ -2026,8 +1947,8 @@ mod tests { tx1.send(1).unwrap(); assert_eq!(rx2.recv().unwrap(), 2); }); - t1.join().ok().unwrap(); - t2.join().ok().unwrap(); + t1.join().ok().expect("thread panicked"); + t2.join().ok().expect("thread panicked"); } #[test] @@ -2225,6 +2146,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn oneshot_single_thread_recv_timeout() { let (tx, rx) = channel(); tx.send(()).unwrap(); @@ -2235,6 +2157,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn stress_recv_timeout_two_threads() { let (tx, rx) = channel(); let stress = stress_factor() + 100; @@ -2265,6 +2188,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn recv_timeout_upgrade() { let (tx, rx) = channel::<()>(); let timeout = Duration::from_millis(1); @@ -2276,6 +2200,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn stress_recv_timeout_shared() { let (tx, rx) = channel(); let stress = stress_factor() + 100; @@ -2306,6 +2231,7 @@ mod tests { } #[test] + #[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 || { @@ -2325,6 +2251,7 @@ mod tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn shared_recv_timeout() { let (tx, rx) = channel(); let total = 5; @@ -2550,6 +2477,7 @@ mod sync_tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn recv_timeout() { let (tx, rx) = sync_channel::<i32>(1); assert_eq!(rx.recv_timeout(Duration::from_millis(1)), Err(RecvTimeoutError::Timeout)); @@ -2639,6 +2567,7 @@ mod sync_tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn stress_recv_timeout_two_threads() { let (tx, rx) = sync_channel::<i32>(0); @@ -2662,6 +2591,7 @@ mod sync_tests { } #[test] + #[cfg_attr(target_env = "sgx", ignore)] // FIXME: https://github.com/fortanix/rust-sgx/issues/31 fn stress_recv_timeout_shared() { const AMT: u32 = 1000; const NTHREADS: u32 = 8; diff --git a/src/libstd/sync/mpsc/oneshot.rs b/src/libstd/sync/mpsc/oneshot.rs index 5c516d5de0f..e7a5cc46b31 100644 --- a/src/libstd/sync/mpsc/oneshot.rs +++ b/src/libstd/sync/mpsc/oneshot.rs @@ -24,7 +24,6 @@ pub use self::Failure::*; pub use self::UpgradeResult::*; -pub use self::SelectionResult::*; use self::MyUpgrade::*; use crate::sync::mpsc::Receiver; @@ -66,12 +65,6 @@ pub enum UpgradeResult { UpWoke(SignalToken), } -pub enum SelectionResult<T> { - SelCanceled, - SelUpgraded(SignalToken, Receiver<T>), - SelSuccess, -} - enum MyUpgrade<T> { NothingSent, SendUsed, @@ -264,71 +257,6 @@ impl<T> Packet<T> { // select implementation //////////////////////////////////////////////////////////////////////////// - // If Ok, the value is whether this port has data, if Err, then the upgraded - // port needs to be checked instead of this one. - pub fn can_recv(&self) -> Result<bool, Receiver<T>> { - unsafe { - match self.state.load(Ordering::SeqCst) { - EMPTY => Ok(false), // Welp, we tried - DATA => Ok(true), // we have some un-acquired data - DISCONNECTED if (*self.data.get()).is_some() => Ok(true), // we have data - DISCONNECTED => { - match ptr::replace(self.upgrade.get(), SendUsed) { - // The other end sent us an upgrade, so we need to - // propagate upwards whether the upgrade can receive - // data - GoUp(upgrade) => Err(upgrade), - - // If the other end disconnected without sending an - // upgrade, then we have data to receive (the channel is - // disconnected). - up => { ptr::write(self.upgrade.get(), up); Ok(true) } - } - } - _ => unreachable!(), // we're the "one blocker" - } - } - } - - // Attempts to start selection on this port. This can either succeed, fail - // because there is data, or fail because there is an upgrade pending. - pub fn start_selection(&self, token: SignalToken) -> SelectionResult<T> { - unsafe { - let ptr = token.cast_to_usize(); - match self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) { - EMPTY => SelSuccess, - DATA => { - drop(SignalToken::cast_from_usize(ptr)); - SelCanceled - } - DISCONNECTED if (*self.data.get()).is_some() => { - drop(SignalToken::cast_from_usize(ptr)); - SelCanceled - } - DISCONNECTED => { - match ptr::replace(self.upgrade.get(), SendUsed) { - // The other end sent us an upgrade, so we need to - // propagate upwards whether the upgrade can receive - // data - GoUp(upgrade) => { - SelUpgraded(SignalToken::cast_from_usize(ptr), upgrade) - } - - // If the other end disconnected without sending an - // upgrade, then we have data to receive (the channel is - // disconnected). - up => { - ptr::write(self.upgrade.get(), up); - drop(SignalToken::cast_from_usize(ptr)); - SelCanceled - } - } - } - _ => unreachable!(), // we're the "one blocker" - } - } - } - // Remove a previous selecting thread from this port. This ensures that the // blocked thread will no longer be visible to any other threads. // diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs deleted file mode 100644 index 19c94908645..00000000000 --- a/src/libstd/sync/mpsc/select.rs +++ /dev/null @@ -1,352 +0,0 @@ -//! Selection over an array of receivers -//! -//! This module contains the implementation machinery necessary for selecting -//! over a number of receivers. One large goal of this module is to provide an -//! efficient interface to selecting over any receiver of any type. -//! -//! This is achieved through an architecture of a "receiver set" in which -//! receivers are added to a set and then the entire set is waited on at once. -//! The set can be waited on multiple times to prevent re-adding each receiver -//! to the set. -//! -//! Usage of this module is currently encouraged to go through the use of the -//! `select!` macro. This macro allows naturally binding of variables to the -//! received values of receivers in a much more natural syntax then usage of the -//! `Select` structure directly. -//! -//! # Examples -//! -//! ```rust -//! #![feature(mpsc_select)] -//! -//! use std::sync::mpsc::channel; -//! -//! let (tx1, rx1) = channel(); -//! let (tx2, rx2) = channel(); -//! -//! tx1.send(1).unwrap(); -//! tx2.send(2).unwrap(); -//! -//! select! { -//! val = rx1.recv() => { -//! assert_eq!(val.unwrap(), 1); -//! }, -//! val = rx2.recv() => { -//! assert_eq!(val.unwrap(), 2); -//! } -//! } -//! ``` - -#![allow(dead_code)] -#![unstable(feature = "mpsc_select", - reason = "This implementation, while likely sufficient, is unsafe and \ - likely to be error prone. At some point in the future this \ - module will be removed.", - issue = "27800")] -#![rustc_deprecated(since = "1.32.0", - reason = "channel selection will be removed in a future release")] - -use core::cell::{Cell, UnsafeCell}; -use core::marker; -use core::ptr; -use core::usize; - -use crate::fmt; -use crate::sync::mpsc::{Receiver, RecvError}; -use crate::sync::mpsc::blocking::{self, SignalToken}; - -/// The "receiver set" of the select interface. This structure is used to manage -/// a set of receivers which are being selected over. -pub struct Select { - inner: UnsafeCell<SelectInner>, - next_id: Cell<usize>, -} - -struct SelectInner { - head: *mut Handle<'static, ()>, - tail: *mut Handle<'static, ()>, -} - -impl !marker::Send for Select {} - -/// A handle to a receiver which is currently a member of a `Select` set of -/// receivers. This handle is used to keep the receiver in the set as well as -/// interact with the underlying receiver. -pub struct Handle<'rx, T:Send+'rx> { - /// The ID of this handle, used to compare against the return value of - /// `Select::wait()`. - id: usize, - selector: *mut SelectInner, - next: *mut Handle<'static, ()>, - prev: *mut Handle<'static, ()>, - added: bool, - packet: &'rx (dyn Packet+'rx), - - // due to our fun transmutes, we be sure to place this at the end. (nothing - // previous relies on T) - rx: &'rx Receiver<T>, -} - -struct Packets { cur: *mut Handle<'static, ()> } - -#[doc(hidden)] -#[derive(PartialEq, Eq)] -pub enum StartResult { - Installed, - Abort, -} - -#[doc(hidden)] -pub trait Packet { - fn can_recv(&self) -> bool; - fn start_selection(&self, token: SignalToken) -> StartResult; - fn abort_selection(&self) -> bool; -} - -impl Select { - /// Creates a new selection structure. This set is initially empty. - /// - /// Usage of this struct directly can sometimes be burdensome, and usage is much easier through - /// the `select!` macro. - /// - /// # Examples - /// - /// ``` - /// #![feature(mpsc_select)] - /// - /// use std::sync::mpsc::Select; - /// - /// let select = Select::new(); - /// ``` - pub fn new() -> Select { - Select { - inner: UnsafeCell::new(SelectInner { - head: ptr::null_mut(), - tail: ptr::null_mut(), - }), - next_id: Cell::new(1), - } - } - - /// Creates a new handle into this receiver set for a new receiver. Note - /// that this does *not* add the receiver to the receiver set, for that you - /// must call the `add` method on the handle itself. - pub fn handle<'a, T: Send>(&'a self, rx: &'a Receiver<T>) -> Handle<'a, T> { - let id = self.next_id.get(); - self.next_id.set(id + 1); - Handle { - id, - selector: self.inner.get(), - next: ptr::null_mut(), - prev: ptr::null_mut(), - added: false, - rx, - packet: rx, - } - } - - /// Waits for an event on this receiver set. The returned value is *not* an - /// index, but rather an ID. This ID can be queried against any active - /// `Handle` structures (each one has an `id` method). The handle with - /// the matching `id` will have some sort of event available on it. The - /// event could either be that data is available or the corresponding - /// channel has been closed. - pub fn wait(&self) -> usize { - self.wait2(true) - } - - /// Helper method for skipping the preflight checks during testing - pub(super) fn wait2(&self, do_preflight_checks: bool) -> usize { - // Note that this is currently an inefficient implementation. We in - // theory have knowledge about all receivers in the set ahead of time, - // so this method shouldn't really have to iterate over all of them yet - // again. The idea with this "receiver set" interface is to get the - // interface right this time around, and later this implementation can - // be optimized. - // - // This implementation can be summarized by: - // - // fn select(receivers) { - // if any receiver ready { return ready index } - // deschedule { - // block on all receivers - // } - // unblock on all receivers - // return ready index - // } - // - // Most notably, the iterations over all of the receivers shouldn't be - // necessary. - unsafe { - // Stage 1: preflight checks. Look for any packets ready to receive - if do_preflight_checks { - for handle in self.iter() { - if (*handle).packet.can_recv() { - return (*handle).id(); - } - } - } - - // Stage 2: begin the blocking process - // - // Create a number of signal tokens, and install each one - // sequentially until one fails. If one fails, then abort the - // selection on the already-installed tokens. - let (wait_token, signal_token) = blocking::tokens(); - for (i, handle) in self.iter().enumerate() { - match (*handle).packet.start_selection(signal_token.clone()) { - StartResult::Installed => {} - StartResult::Abort => { - // Go back and abort the already-begun selections - for handle in self.iter().take(i) { - (*handle).packet.abort_selection(); - } - return (*handle).id; - } - } - } - - // Stage 3: no messages available, actually block - wait_token.wait(); - - // Stage 4: there *must* be message available; find it. - // - // Abort the selection process on each receiver. If the abort - // process returns `true`, then that means that the receiver is - // ready to receive some data. Note that this also means that the - // receiver may have yet to have fully read the `to_wake` field and - // woken us up (although the wakeup is guaranteed to fail). - // - // This situation happens in the window of where a sender invokes - // increment(), sees -1, and then decides to wake up the thread. After - // all this is done, the sending thread will set `selecting` to - // `false`. Until this is done, we cannot return. If we were to - // return, then a sender could wake up a receiver which has gone - // back to sleep after this call to `select`. - // - // Note that it is a "fairly small window" in which an increment() - // views that it should wake a thread up until the `selecting` bit - // is set to false. For now, the implementation currently just spins - // in a yield loop. This is very distasteful, but this - // implementation is already nowhere near what it should ideally be. - // A rewrite should focus on avoiding a yield loop, and for now this - // implementation is tying us over to a more efficient "don't - // iterate over everything every time" implementation. - let mut ready_id = usize::MAX; - for handle in self.iter() { - if (*handle).packet.abort_selection() { - ready_id = (*handle).id; - } - } - - // We must have found a ready receiver - assert!(ready_id != usize::MAX); - return ready_id; - } - } - - fn iter(&self) -> Packets { Packets { cur: unsafe { &*self.inner.get() }.head } } -} - -impl<'rx, T: Send> Handle<'rx, T> { - /// Retrieves the ID of this handle. - #[inline] - pub fn id(&self) -> usize { self.id } - - /// Blocks to receive a value on the underlying receiver, returning `Some` on - /// success or `None` if the channel disconnects. This function has the same - /// semantics as `Receiver.recv` - pub fn recv(&mut self) -> Result<T, RecvError> { self.rx.recv() } - - /// Adds this handle to the receiver set that the handle was created from. This - /// method can be called multiple times, but it has no effect if `add` was - /// called previously. - /// - /// This method is unsafe because it requires that the `Handle` is not moved - /// while it is added to the `Select` set. - pub unsafe fn add(&mut self) { - if self.added { return } - let selector = &mut *self.selector; - let me = self as *mut Handle<'rx, T> as *mut Handle<'static, ()>; - - if selector.head.is_null() { - selector.head = me; - selector.tail = me; - } else { - (*me).prev = selector.tail; - assert!((*me).next.is_null()); - (*selector.tail).next = me; - selector.tail = me; - } - self.added = true; - } - - /// Removes this handle from the `Select` set. This method is unsafe because - /// it has no guarantee that the `Handle` was not moved since `add` was - /// called. - pub unsafe fn remove(&mut self) { - if !self.added { return } - - let selector = &mut *self.selector; - let me = self as *mut Handle<'rx, T> as *mut Handle<'static, ()>; - - if self.prev.is_null() { - assert_eq!(selector.head, me); - selector.head = self.next; - } else { - (*self.prev).next = self.next; - } - if self.next.is_null() { - assert_eq!(selector.tail, me); - selector.tail = self.prev; - } else { - (*self.next).prev = self.prev; - } - - self.next = ptr::null_mut(); - self.prev = ptr::null_mut(); - - self.added = false; - } -} - -impl Drop for Select { - fn drop(&mut self) { - unsafe { - assert!((&*self.inner.get()).head.is_null()); - assert!((&*self.inner.get()).tail.is_null()); - } - } -} - -impl<T: Send> Drop for Handle<'_, T> { - fn drop(&mut self) { - unsafe { self.remove() } - } -} - -impl Iterator for Packets { - type Item = *mut Handle<'static, ()>; - - fn next(&mut self) -> Option<*mut Handle<'static, ()>> { - if self.cur.is_null() { - None - } else { - let ret = Some(self.cur); - unsafe { self.cur = (*self.cur).next; } - ret - } - } -} - -impl fmt::Debug for Select { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Select").finish() - } -} - -impl<T: Send> fmt::Debug for Handle<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Handle").finish() - } -} diff --git a/src/libstd/sync/mpsc/select_tests.rs b/src/libstd/sync/mpsc/select_tests.rs deleted file mode 100644 index 18d93462c78..00000000000 --- a/src/libstd/sync/mpsc/select_tests.rs +++ /dev/null @@ -1,413 +0,0 @@ -#![allow(unused_imports)] - -/// This file exists to hack around https://github.com/rust-lang/rust/issues/47238 - -use crate::thread; -use crate::sync::mpsc::*; - -// Don't use the libstd version so we can pull in the right Select structure -// (std::comm points at the wrong one) -macro_rules! select { - ( - $($name:pat = $rx:ident.$meth:ident() => $code:expr),+ - ) => ({ - let sel = Select::new(); - $( let mut $rx = sel.handle(&$rx); )+ - unsafe { - $( $rx.add(); )+ - } - let ret = sel.wait(); - $( if ret == $rx.id() { let $name = $rx.$meth(); $code } else )+ - { unreachable!() } - }) -} - -#[test] -fn smoke() { - let (tx1, rx1) = channel::<i32>(); - let (tx2, rx2) = channel::<i32>(); - tx1.send(1).unwrap(); - select! { - foo = rx1.recv() => { assert_eq!(foo.unwrap(), 1); }, - _bar = rx2.recv() => { panic!() } - } - tx2.send(2).unwrap(); - select! { - _foo = rx1.recv() => { panic!() }, - bar = rx2.recv() => { assert_eq!(bar.unwrap(), 2) } - } - drop(tx1); - select! { - foo = rx1.recv() => { assert!(foo.is_err()); }, - _bar = rx2.recv() => { panic!() } - } - drop(tx2); - select! { - bar = rx2.recv() => { assert!(bar.is_err()); } - } -} - -#[test] -fn smoke2() { - let (_tx1, rx1) = channel::<i32>(); - let (_tx2, rx2) = channel::<i32>(); - let (_tx3, rx3) = channel::<i32>(); - let (_tx4, rx4) = channel::<i32>(); - let (tx5, rx5) = channel::<i32>(); - tx5.send(4).unwrap(); - select! { - _foo = rx1.recv() => { panic!("1") }, - _foo = rx2.recv() => { panic!("2") }, - _foo = rx3.recv() => { panic!("3") }, - _foo = rx4.recv() => { panic!("4") }, - foo = rx5.recv() => { assert_eq!(foo.unwrap(), 4); } - } -} - -#[test] -fn closed() { - let (_tx1, rx1) = channel::<i32>(); - let (tx2, rx2) = channel::<i32>(); - drop(tx2); - - select! { - _a1 = rx1.recv() => { panic!() }, - a2 = rx2.recv() => { assert!(a2.is_err()); } - } -} - -#[test] -fn unblocks() { - let (tx1, rx1) = channel::<i32>(); - let (_tx2, rx2) = channel::<i32>(); - let (tx3, rx3) = channel::<i32>(); - - let _t = thread::spawn(move|| { - for _ in 0..20 { thread::yield_now(); } - tx1.send(1).unwrap(); - rx3.recv().unwrap(); - for _ in 0..20 { thread::yield_now(); } - }); - - select! { - a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, - _b = rx2.recv() => { panic!() } - } - tx3.send(1).unwrap(); - select! { - a = rx1.recv() => { assert!(a.is_err()) }, - _b = rx2.recv() => { panic!() } - } -} - -#[test] -fn both_ready() { - let (tx1, rx1) = channel::<i32>(); - let (tx2, rx2) = channel::<i32>(); - let (tx3, rx3) = channel::<()>(); - - let _t = thread::spawn(move|| { - for _ in 0..20 { thread::yield_now(); } - tx1.send(1).unwrap(); - tx2.send(2).unwrap(); - rx3.recv().unwrap(); - }); - - select! { - a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, - a = rx2.recv() => { assert_eq!(a.unwrap(), 2); } - } - select! { - a = rx1.recv() => { assert_eq!(a.unwrap(), 1); }, - a = rx2.recv() => { assert_eq!(a.unwrap(), 2); } - } - assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty)); - assert_eq!(rx2.try_recv(), Err(TryRecvError::Empty)); - tx3.send(()).unwrap(); -} - -#[test] -fn stress() { - const AMT: i32 = 10000; - let (tx1, rx1) = channel::<i32>(); - let (tx2, rx2) = channel::<i32>(); - let (tx3, rx3) = channel::<()>(); - - let _t = thread::spawn(move|| { - for i in 0..AMT { - if i % 2 == 0 { - tx1.send(i).unwrap(); - } else { - tx2.send(i).unwrap(); - } - rx3.recv().unwrap(); - } - }); - - for i in 0..AMT { - select! { - i1 = rx1.recv() => { assert!(i % 2 == 0 && i == i1.unwrap()); }, - i2 = rx2.recv() => { assert!(i % 2 == 1 && i == i2.unwrap()); } - } - tx3.send(()).unwrap(); - } -} - -#[allow(unused_must_use)] -#[test] -fn cloning() { - let (tx1, rx1) = channel::<i32>(); - let (_tx2, rx2) = channel::<i32>(); - let (tx3, rx3) = channel::<()>(); - - let _t = thread::spawn(move|| { - rx3.recv().unwrap(); - tx1.clone(); - assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty)); - tx1.send(2).unwrap(); - rx3.recv().unwrap(); - }); - - tx3.send(()).unwrap(); - select! { - _i1 = rx1.recv() => {}, - _i2 = rx2.recv() => panic!() - } - tx3.send(()).unwrap(); -} - -#[allow(unused_must_use)] -#[test] -fn cloning2() { - let (tx1, rx1) = channel::<i32>(); - let (_tx2, rx2) = channel::<i32>(); - let (tx3, rx3) = channel::<()>(); - - let _t = thread::spawn(move|| { - rx3.recv().unwrap(); - tx1.clone(); - assert_eq!(rx3.try_recv(), Err(TryRecvError::Empty)); - tx1.send(2).unwrap(); - rx3.recv().unwrap(); - }); - - tx3.send(()).unwrap(); - select! { - _i1 = rx1.recv() => {}, - _i2 = rx2.recv() => panic!() - } - tx3.send(()).unwrap(); -} - -#[test] -fn cloning3() { - let (tx1, rx1) = channel::<()>(); - let (tx2, rx2) = channel::<()>(); - let (tx3, rx3) = channel::<()>(); - let _t = thread::spawn(move|| { - let s = Select::new(); - let mut h1 = s.handle(&rx1); - let mut h2 = s.handle(&rx2); - unsafe { h2.add(); } - unsafe { h1.add(); } - assert_eq!(s.wait(), h2.id()); - tx3.send(()).unwrap(); - }); - - for _ in 0..1000 { thread::yield_now(); } - drop(tx1.clone()); - tx2.send(()).unwrap(); - rx3.recv().unwrap(); -} - -#[test] -fn preflight1() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - select! { - _n = rx.recv() => {} - } -} - -#[test] -fn preflight2() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - tx.send(()).unwrap(); - select! { - _n = rx.recv() => {} - } -} - -#[test] -fn preflight3() { - let (tx, rx) = channel(); - drop(tx.clone()); - tx.send(()).unwrap(); - select! { - _n = rx.recv() => {} - } -} - -#[test] -fn preflight4() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id()); -} - -#[test] -fn preflight5() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - tx.send(()).unwrap(); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id()); -} - -#[test] -fn preflight6() { - let (tx, rx) = channel(); - drop(tx.clone()); - tx.send(()).unwrap(); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id()); -} - -#[test] -fn preflight7() { - let (tx, rx) = channel::<()>(); - drop(tx); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id()); -} - -#[test] -fn preflight8() { - let (tx, rx) = channel(); - tx.send(()).unwrap(); - drop(tx); - rx.recv().unwrap(); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id()); -} - -#[test] -fn preflight9() { - let (tx, rx) = channel(); - drop(tx.clone()); - tx.send(()).unwrap(); - drop(tx); - rx.recv().unwrap(); - let s = Select::new(); - let mut h = s.handle(&rx); - unsafe { h.add(); } - assert_eq!(s.wait2(false), h.id()); -} - -#[test] -fn oneshot_data_waiting() { - let (tx1, rx1) = channel(); - let (tx2, rx2) = channel(); - let _t = thread::spawn(move|| { - select! { - _n = rx1.recv() => {} - } - tx2.send(()).unwrap(); - }); - - for _ in 0..100 { thread::yield_now() } - tx1.send(()).unwrap(); - rx2.recv().unwrap(); -} - -#[test] -fn stream_data_waiting() { - let (tx1, rx1) = channel(); - let (tx2, rx2) = channel(); - tx1.send(()).unwrap(); - tx1.send(()).unwrap(); - rx1.recv().unwrap(); - rx1.recv().unwrap(); - let _t = thread::spawn(move|| { - select! { - _n = rx1.recv() => {} - } - tx2.send(()).unwrap(); - }); - - for _ in 0..100 { thread::yield_now() } - tx1.send(()).unwrap(); - rx2.recv().unwrap(); -} - -#[test] -fn shared_data_waiting() { - let (tx1, rx1) = channel(); - let (tx2, rx2) = channel(); - drop(tx1.clone()); - tx1.send(()).unwrap(); - rx1.recv().unwrap(); - let _t = thread::spawn(move|| { - select! { - _n = rx1.recv() => {} - } - tx2.send(()).unwrap(); - }); - - for _ in 0..100 { thread::yield_now() } - tx1.send(()).unwrap(); - rx2.recv().unwrap(); -} - -#[test] -fn sync1() { - let (tx, rx) = sync_channel::<i32>(1); - tx.send(1).unwrap(); - select! { - n = rx.recv() => { assert_eq!(n.unwrap(), 1); } - } -} - -#[test] -fn sync2() { - let (tx, rx) = sync_channel::<i32>(0); - let _t = thread::spawn(move|| { - for _ in 0..100 { thread::yield_now() } - tx.send(1).unwrap(); - }); - select! { - n = rx.recv() => { assert_eq!(n.unwrap(), 1); } - } -} - -#[test] -fn sync3() { - let (tx1, rx1) = sync_channel::<i32>(0); - let (tx2, rx2): (Sender<i32>, Receiver<i32>) = channel(); - let _t = thread::spawn(move|| { tx1.send(1).unwrap(); }); - let _t = thread::spawn(move|| { tx2.send(2).unwrap(); }); - select! { - n = rx1.recv() => { - let n = n.unwrap(); - assert_eq!(n, 1); - assert_eq!(rx2.recv().unwrap(), 2); - }, - n = rx2.recv() => { - let n = n.unwrap(); - assert_eq!(n, 2); - assert_eq!(rx1.recv().unwrap(), 1); - } - } -} diff --git a/src/libstd/sync/mpsc/shared.rs b/src/libstd/sync/mpsc/shared.rs index 6a5d861f0e9..dbcdcdac932 100644 --- a/src/libstd/sync/mpsc/shared.rs +++ b/src/libstd/sync/mpsc/shared.rs @@ -9,6 +9,7 @@ /// channels are quite similar, and this is no coincidence! pub use self::Failure::*; +use self::StartResult::*; use core::cmp; use core::intrinsics::abort; @@ -19,8 +20,6 @@ use crate::ptr; use crate::sync::atomic::{AtomicUsize, AtomicIsize, AtomicBool, Ordering}; use crate::sync::mpsc::blocking::{self, SignalToken}; use crate::sync::mpsc::mpsc_queue as mpsc; -use crate::sync::mpsc::select::StartResult::*; -use crate::sync::mpsc::select::StartResult; use crate::sync::{Mutex, MutexGuard}; use crate::thread; use crate::time::Instant; @@ -57,6 +56,12 @@ pub enum Failure { Disconnected, } +#[derive(PartialEq, Eq)] +enum StartResult { + Installed, + Abort, +} + impl<T> Packet<T> { // Creation of a packet *must* be followed by a call to postinit_lock // and later by inherit_blocker @@ -78,7 +83,7 @@ impl<T> Packet<T> { // In other case mutex data will be duplicated while cloning // and that could cause problems on platforms where it is // represented by opaque data structure - pub fn postinit_lock(&self) -> MutexGuard<()> { + pub fn postinit_lock(&self) -> MutexGuard<'_, ()> { self.select_lock.lock().unwrap() } @@ -89,7 +94,7 @@ impl<T> Packet<T> { // This can only be called at channel-creation time pub fn inherit_blocker(&self, token: Option<SignalToken>, - guard: MutexGuard<()>) { + guard: MutexGuard<'_, ()>) { token.map(|token| { assert_eq!(self.cnt.load(Ordering::SeqCst), 0); assert_eq!(self.to_wake.load(Ordering::SeqCst), 0); @@ -394,16 +399,6 @@ impl<T> Packet<T> { // select implementation //////////////////////////////////////////////////////////////////////////// - // Helper function for select, tests whether this port can receive without - // blocking (obviously not an atomic decision). - // - // This is different than the stream version because there's no need to peek - // at the queue, we can just look at the local count. - pub fn can_recv(&self) -> bool { - let cnt = self.cnt.load(Ordering::SeqCst); - cnt == DISCONNECTED || cnt - unsafe { *self.steals.get() } > 0 - } - // increment the count on the channel (used for selection) fn bump(&self, amt: isize) -> isize { match self.cnt.fetch_add(amt, Ordering::SeqCst) { @@ -415,22 +410,6 @@ impl<T> Packet<T> { } } - // Inserts the signal token for selection on this port, returning true if - // blocking should proceed. - // - // The code here is the same as in stream.rs, except that it doesn't need to - // peek at the channel to see if an upgrade is pending. - pub fn start_selection(&self, token: SignalToken) -> StartResult { - match self.decrement(token) { - Installed => Installed, - Abort => { - let prev = self.bump(1); - assert!(prev == DISCONNECTED || prev >= 0); - Abort - } - } - } - // Cancels a previous thread waiting on this port, returning whether there's // data on the port. // diff --git a/src/libstd/sync/mpsc/stream.rs b/src/libstd/sync/mpsc/stream.rs index 7ae6f68b514..40877282761 100644 --- a/src/libstd/sync/mpsc/stream.rs +++ b/src/libstd/sync/mpsc/stream.rs @@ -9,7 +9,6 @@ pub use self::Failure::*; pub use self::UpgradeResult::*; -pub use self::SelectionResult::*; use self::Message::*; use core::cmp; @@ -60,12 +59,6 @@ pub enum UpgradeResult { UpWoke(SignalToken), } -pub enum SelectionResult<T> { - SelSuccess, - SelCanceled, - SelUpgraded(SignalToken, Receiver<T>), -} - // Any message could contain an "upgrade request" to a new shared port, so the // internal queue it's a queue of T, but rather Message<T> enum Message<T> { @@ -338,27 +331,6 @@ impl<T> Packet<T> { // select implementation //////////////////////////////////////////////////////////////////////////// - // Tests to see whether this port can receive without blocking. If Ok is - // returned, then that's the answer. If Err is returned, then the returned - // port needs to be queried instead (an upgrade happened) - pub fn can_recv(&self) -> Result<bool, Receiver<T>> { - // We peek at the queue to see if there's anything on it, and we use - // this return value to determine if we should pop from the queue and - // upgrade this channel immediately. If it looks like we've got an - // upgrade pending, then go through the whole recv rigamarole to update - // the internal state. - match self.queue.peek() { - Some(&mut GoUp(..)) => { - match self.recv(None) { - Err(Upgraded(port)) => Err(port), - _ => unreachable!(), - } - } - Some(..) => Ok(true), - None => Ok(false) - } - } - // increment the count on the channel (used for selection) fn bump(&self, amt: isize) -> isize { match self.queue.producer_addition().cnt.fetch_add(amt, Ordering::SeqCst) { @@ -370,31 +342,6 @@ impl<T> Packet<T> { } } - // Attempts to start selecting on this port. Like a oneshot, this can fail - // immediately because of an upgrade. - pub fn start_selection(&self, token: SignalToken) -> SelectionResult<T> { - match self.decrement(token) { - Ok(()) => SelSuccess, - Err(token) => { - let ret = match self.queue.peek() { - Some(&mut GoUp(..)) => { - match self.queue.pop() { - Some(GoUp(port)) => SelUpgraded(token, port), - _ => unreachable!(), - } - } - Some(..) => SelCanceled, - None => SelCanceled, - }; - // Undo our decrement above, and we should be guaranteed that the - // previous value is positive because we're not going to sleep - let prev = self.bump(1); - assert!(prev == DISCONNECTED || prev >= 0); - ret - } - } - } - // Removes a previous thread from being blocked in this port pub fn abort_selection(&self, was_upgrade: bool) -> Result<bool, Receiver<T>> { diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs index 485234a9495..58a4b716afb 100644 --- a/src/libstd/sync/mpsc/sync.rs +++ b/src/libstd/sync/mpsc/sync.rs @@ -33,7 +33,6 @@ use core::ptr; use crate::sync::atomic::{Ordering, AtomicUsize}; use crate::sync::mpsc::blocking::{self, WaitToken, SignalToken}; -use crate::sync::mpsc::select::StartResult::{self, Installed, Abort}; use crate::sync::{Mutex, MutexGuard}; use crate::time::Instant; @@ -141,7 +140,7 @@ fn wait_timeout_receiver<'a, 'b, T>(lock: &'a Mutex<State<T>>, new_guard } -fn abort_selection<'a, T>(guard: &mut MutexGuard<'a , State<T>>) -> bool { +fn abort_selection<T>(guard: &mut MutexGuard<'_, State<T>>) -> bool { match mem::replace(&mut guard.blocker, NoneBlocked) { NoneBlocked => true, BlockedSender(token) => { @@ -153,7 +152,7 @@ fn abort_selection<'a, T>(guard: &mut MutexGuard<'a , State<T>>) -> bool { } /// Wakes up a thread, dropping the lock at the correct time -fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) { +fn wakeup<T>(token: SignalToken, guard: MutexGuard<'_, State<T>>) { // We need to be careful to wake up the waiting thread *outside* of the mutex // in case it incurs a context switch. drop(guard); @@ -161,20 +160,20 @@ fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) { } impl<T> Packet<T> { - pub fn new(cap: usize) -> Packet<T> { + pub fn new(capacity: usize) -> Packet<T> { Packet { channels: AtomicUsize::new(1), lock: Mutex::new(State { disconnected: false, blocker: NoneBlocked, - cap, + cap: capacity, canceled: None, queue: Queue { head: ptr::null_mut(), tail: ptr::null_mut(), }, buf: Buffer { - buf: (0..cap + if cap == 0 {1} else {0}).map(|_| None).collect(), + buf: (0..capacity + if capacity == 0 {1} else {0}).map(|_| None).collect(), start: 0, size: 0, }, @@ -184,12 +183,12 @@ impl<T> Packet<T> { // wait until a send slot is available, returning locked access to // the channel state. - fn acquire_send_slot(&self) -> MutexGuard<State<T>> { + fn acquire_send_slot(&self) -> MutexGuard<'_, State<T>> { let mut node = Node { token: None, next: ptr::null_mut() }; loop { let mut guard = self.lock.lock().unwrap(); // are we ready to go? - if guard.disconnected || guard.buf.size() < guard.buf.cap() { + if guard.disconnected || guard.buf.size() < guard.buf.capacity() { return guard; } // no room; actually block @@ -231,7 +230,7 @@ impl<T> Packet<T> { let mut guard = self.lock.lock().unwrap(); if guard.disconnected { Err(super::TrySendError::Disconnected(t)) - } else if guard.buf.size() == guard.buf.cap() { + } else if guard.buf.size() == guard.buf.capacity() { Err(super::TrySendError::Full(t)) } else if guard.cap == 0 { // With capacity 0, even though we have buffer space we can't @@ -249,7 +248,7 @@ impl<T> Packet<T> { // If the buffer has some space and the capacity isn't 0, then we // just enqueue the data for later retrieval, ensuring to wake up // any blocked receiver if there is one. - assert!(guard.buf.size() < guard.buf.cap()); + assert!(guard.buf.size() < guard.buf.capacity()); guard.buf.enqueue(t); match mem::replace(&mut guard.blocker, NoneBlocked) { BlockedReceiver(token) => wakeup(token, guard), @@ -316,7 +315,7 @@ impl<T> Packet<T> { // * `waited` - flag if the receiver blocked to receive some data, or if it // just picked up some data on the way out // * `guard` - the lock guard that is held over this channel's lock - fn wakeup_senders(&self, waited: bool, mut guard: MutexGuard<State<T>>) { + fn wakeup_senders(&self, waited: bool, mut guard: MutexGuard<'_, State<T>>) { let pending_sender1: Option<SignalToken> = guard.queue.dequeue(); // If this is a no-buffer channel (cap == 0), then if we didn't wait we @@ -384,7 +383,7 @@ impl<T> Packet<T> { // needs to be careful to destroy the data *outside* of the lock to // prevent deadlock. let _data = if guard.cap != 0 { - mem::replace(&mut guard.buf.buf, Vec::new()) + mem::take(&mut guard.buf.buf) } else { Vec::new() }; @@ -406,42 +405,6 @@ impl<T> Packet<T> { while let Some(token) = queue.dequeue() { token.signal(); } waiter.map(|t| t.signal()); } - - //////////////////////////////////////////////////////////////////////////// - // select implementation - //////////////////////////////////////////////////////////////////////////// - - // If Ok, the value is whether this port has data, if Err, then the upgraded - // port needs to be checked instead of this one. - pub fn can_recv(&self) -> bool { - let guard = self.lock.lock().unwrap(); - guard.disconnected || guard.buf.size() > 0 - } - - // Attempts to start selection on this port. This can either succeed or fail - // because there is data waiting. - pub fn start_selection(&self, token: SignalToken) -> StartResult { - let mut guard = self.lock.lock().unwrap(); - if guard.disconnected || guard.buf.size() > 0 { - Abort - } else { - match mem::replace(&mut guard.blocker, BlockedReceiver(token)) { - NoneBlocked => {} - BlockedSender(..) => unreachable!(), - BlockedReceiver(..) => unreachable!(), - } - Installed - } - } - - // Remove a previous selecting thread from this port. This ensures that the - // blocked thread will no longer be visible to any other threads. - // - // The return value indicates whether there's data on this port. - pub fn abort_selection(&self) -> bool { - let mut guard = self.lock.lock().unwrap(); - abort_selection(&mut guard) - } } impl<T> Drop for Packet<T> { @@ -475,7 +438,7 @@ impl<T> Buffer<T> { } fn size(&self) -> usize { self.size } - fn cap(&self) -> usize { self.buf.len() } + fn capacity(&self) -> usize { self.buf.len() } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 6b812e65b72..87c2318a937 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -215,7 +215,7 @@ impl<T: ?Sized> Mutex<T> { /// assert_eq!(*mutex.lock().unwrap(), 10); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn lock(&self) -> LockResult<MutexGuard<T>> { + pub fn lock(&self) -> LockResult<MutexGuard<'_, T>> { unsafe { self.inner.raw_lock(); MutexGuard::new(self) @@ -258,7 +258,7 @@ impl<T: ?Sized> Mutex<T> { /// assert_eq!(*mutex.lock().unwrap(), 10); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn try_lock(&self) -> TryLockResult<MutexGuard<T>> { + pub fn try_lock(&self) -> TryLockResult<MutexGuard<'_, T>> { unsafe { if self.inner.try_lock() { Ok(MutexGuard::new(self)?) @@ -376,6 +376,8 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Mutex<T> { impl<T> From<T> for Mutex<T> { /// Creates a new mutex in an unlocked state ready for use. /// This is equivalent to [`Mutex::new`]. + /// + /// [`Mutex::new`]: ../../std/sync/struct.Mutex.html#method.new fn from(t: T) -> Self { Mutex::new(t) } @@ -391,7 +393,7 @@ impl<T: ?Sized + Default> Default for Mutex<T> { #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.try_lock() { Ok(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(), Err(TryLockError::Poisoned(err)) => { @@ -400,7 +402,9 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for Mutex<T> { Err(TryLockError::WouldBlock) => { struct LockedPlaceholder; impl fmt::Debug for LockedPlaceholder { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("<locked>") } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("<locked>") + } } f.debug_struct("Mutex").field("data", &LockedPlaceholder).finish() @@ -449,14 +453,14 @@ impl<T: ?Sized> Drop for MutexGuard<'_, T> { #[stable(feature = "std_debug", since = "1.16.0")] impl<T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } #[stable(feature = "std_guard_impls", since = "1.20.0")] impl<T: ?Sized + fmt::Display> fmt::Display for MutexGuard<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) } } diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index a036c266662..e529b8c4227 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -115,6 +115,11 @@ pub struct OnceState { /// static START: Once = ONCE_INIT; /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[rustc_deprecated( + since = "1.38.0", + reason = "the `new` function is now preferred", + suggestion = "Once::new()", +)] pub const ONCE_INIT: Once = Once::new(); // Four states that a Once can be in, encoded into the lower bits of `state` in @@ -431,7 +436,7 @@ impl Once { #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for Once { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad("Once { .. }") } } diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 0be83c76d62..b1b56f321fc 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -180,7 +180,7 @@ impl<T: ?Sized> RwLock<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn read(&self) -> LockResult<RwLockReadGuard<T>> { + pub fn read(&self) -> LockResult<RwLockReadGuard<'_, T>> { unsafe { self.inner.read(); RwLockReadGuard::new(self) @@ -219,7 +219,7 @@ impl<T: ?Sized> RwLock<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> { + pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<'_, T>> { unsafe { if self.inner.try_read() { Ok(RwLockReadGuard::new(self)?) @@ -262,7 +262,7 @@ impl<T: ?Sized> RwLock<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> { + pub fn write(&self) -> LockResult<RwLockWriteGuard<'_, T>> { unsafe { self.inner.write(); RwLockWriteGuard::new(self) @@ -301,7 +301,7 @@ impl<T: ?Sized> RwLock<T> { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> { + pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<'_, T>> { unsafe { if self.inner.try_write() { Ok(RwLockWriteGuard::new(self)?) @@ -421,7 +421,7 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for RwLock<T> { #[stable(feature = "rust1", since = "1.0.0")] impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.try_read() { Ok(guard) => f.debug_struct("RwLock").field("data", &&*guard).finish(), Err(TryLockError::Poisoned(err)) => { @@ -430,7 +430,9 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> { Err(TryLockError::WouldBlock) => { struct LockedPlaceholder; impl fmt::Debug for LockedPlaceholder { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.write_str("<locked>") } + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("<locked>") + } } f.debug_struct("RwLock").field("data", &LockedPlaceholder).finish() @@ -451,6 +453,8 @@ impl<T: Default> Default for RwLock<T> { impl<T> From<T> for RwLock<T> { /// Creates a new instance of an `RwLock<T>` which is unlocked. /// This is equivalent to [`RwLock::new`]. + /// + /// [`RwLock::new`]: ../../std/sync/struct.RwLock.html#method.new fn from(t: T) -> Self { RwLock::new(t) } @@ -481,7 +485,7 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { #[stable(feature = "std_debug", since = "1.16.0")] impl<T: fmt::Debug> fmt::Debug for RwLockReadGuard<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RwLockReadGuard") .field("lock", &self.__lock) .finish() @@ -490,14 +494,14 @@ impl<T: fmt::Debug> fmt::Debug for RwLockReadGuard<'_, T> { #[stable(feature = "std_guard_impls", since = "1.20.0")] impl<T: ?Sized + fmt::Display> fmt::Display for RwLockReadGuard<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) } } #[stable(feature = "std_debug", since = "1.16.0")] impl<T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RwLockWriteGuard") .field("lock", &self.__lock) .finish() @@ -506,7 +510,7 @@ impl<T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'_, T> { #[stable(feature = "std_guard_impls", since = "1.20.0")] impl<T: ?Sized + fmt::Display> fmt::Display for RwLockWriteGuard<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { (**self).fmt(f) } } |
