diff options
| author | Stein Somers <git@steinsomers.be> | 2019-02-18 00:31:41 +0100 |
|---|---|---|
| committer | Stein Somers <git@steinsomers.be> | 2019-02-18 00:31:41 +0100 |
| commit | 01bebdf19321a1597f35c2fc2130f1627e944bcf (patch) | |
| tree | 2c71bc6a77545eacabdc67b1fcaa5f52dd22878c /src/libstd/sync | |
| parent | 0b9ad6e6fd017837647eed8e5ae824d1f6e278b2 (diff) | |
| parent | 9a3392e174a432a5f06c1157befc1ce0fae74bec (diff) | |
| download | rust-01bebdf19321a1597f35c2fc2130f1627e944bcf.tar.gz rust-01bebdf19321a1597f35c2fc2130f1627e944bcf.zip | |
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'src/libstd/sync')
| -rw-r--r-- | src/libstd/sync/barrier.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sync/condvar.rs | 10 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/blocking.rs | 6 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/mod.rs | 5 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/select.rs | 424 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/select_tests.rs | 413 | ||||
| -rw-r--r-- | src/libstd/sync/mpsc/shared.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sync/mutex.rs | 2 | ||||
| -rw-r--r-- | src/libstd/sync/once.rs | 6 | ||||
| -rw-r--r-- | src/libstd/sync/rwlock.rs | 4 |
10 files changed, 438 insertions, 436 deletions
diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index f248c721e9a..bc2e14d436a 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -159,7 +159,7 @@ impl fmt::Debug for BarrierWaitResult { } impl BarrierWaitResult { - /// Returns whether this thread from [`wait`] is the "leader thread". + /// Returns `true` if this thread from [`wait`] is the "leader thread". /// /// Only one thread will have `true` returned from their result, all other /// threads will have `false` returned. diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 76887379106..036aff090ea 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -17,7 +17,7 @@ use time::{Duration, Instant}; pub struct WaitTimeoutResult(bool); impl WaitTimeoutResult { - /// Returns whether the wait was known to have timed out. + /// Returns `true` if the wait was known to have timed out. /// /// # Examples /// @@ -343,13 +343,13 @@ impl Condvar { /// /// Note that the best effort is made to ensure that the time waited is /// measured with a monotonic clock, and not affected by the changes made to - /// the system time. This function is susceptible to spurious wakeups. + /// the system time. This function is susceptible to spurious wakeups. /// Condition variables normally have a boolean predicate associated with /// them, and the predicate must always be checked each time this function - /// returns to protect against spurious wakeups. Additionally, it is + /// returns to protect against spurious wakeups. Additionally, it is /// typically desirable for the time-out to not exceed some duration in /// spite of spurious wakes, thus the sleep-duration is decremented by the - /// amount slept. Alternatively, use the `wait_timeout_until` method + /// amount slept. Alternatively, use the `wait_timeout_until` method /// to wait until a condition is met with a total time-out regardless /// of spurious wakes. /// @@ -413,7 +413,7 @@ impl Condvar { } /// Waits on this condition variable for a notification, timing out after a - /// specified duration. Spurious wakes will not cause this function to + /// specified duration. Spurious wakes will not cause this function to /// return. /// /// The semantics of this function are equivalent to [`wait_until`] except diff --git a/src/libstd/sync/mpsc/blocking.rs b/src/libstd/sync/mpsc/blocking.rs index ae5a18adbb3..eaf09a16756 100644 --- a/src/libstd/sync/mpsc/blocking.rs +++ b/src/libstd/sync/mpsc/blocking.rs @@ -50,14 +50,14 @@ impl SignalToken { wake } - /// Convert to an unsafe usize value. Useful for storing in a pipe's state + /// Converts to an unsafe usize value. Useful for storing in a pipe's state /// flag. #[inline] pub unsafe fn cast_to_usize(self) -> usize { mem::transmute(self.inner) } - /// Convert from an unsafe usize value. Useful for retrieving a pipe's state + /// Converts from an unsafe usize value. Useful for retrieving a pipe's state /// flag. #[inline] pub unsafe fn cast_from_usize(signal_ptr: usize) -> SignalToken { @@ -72,7 +72,7 @@ impl WaitToken { } } - /// Returns true if we wake up normally, false otherwise. + /// Returns `true` if we wake up normally. pub fn wait_max_until(self, end: Instant) -> bool { while !self.inner.woken.load(Ordering::SeqCst) { let now = Instant::now(); diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 446c164965d..5273345c6b4 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -279,6 +279,9 @@ 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; @@ -789,7 +792,7 @@ impl<T> Sender<T> { /// where the corresponding receiver has already been deallocated. Note /// that a return value of [`Err`] means that the data will never be /// received, but a return value of [`Ok`] does *not* mean that the data - /// will be received. It is possible for the corresponding receiver to + /// will be received. It is possible for the corresponding receiver to /// hang up immediately after this function returns [`Ok`]. /// /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs index 8f41680a818..8f6f9818d5c 100644 --- a/src/libstd/sync/mpsc/select.rs +++ b/src/libstd/sync/mpsc/select.rs @@ -72,11 +72,11 @@ struct SelectInner { 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 +/// 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()` + /// `Select::wait()`. id: usize, selector: *mut SelectInner, next: *mut Handle<'static, ()>, @@ -148,7 +148,7 @@ impl Select { } /// 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 + /// 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 @@ -158,7 +158,7 @@ impl Select { } /// Helper method for skipping the preflight checks during testing - fn wait2(&self, do_preflight_checks: bool) -> usize { + 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 @@ -251,7 +251,7 @@ impl Select { } impl<'rx, T: Send> Handle<'rx, T> { - /// Retrieves the id of this handle. + /// Retrieves the ID of this handle. #[inline] pub fn id(&self) -> usize { self.id } @@ -352,417 +352,3 @@ impl<'rx, T:Send+'rx> fmt::Debug for Handle<'rx, T> { f.debug_struct("Handle").finish() } } - -#[allow(unused_imports)] -#[cfg(all(test, not(target_os = "emscripten")))] -mod tests { - use thread; - use 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/select_tests.rs b/src/libstd/sync/mpsc/select_tests.rs new file mode 100644 index 00000000000..be048511caa --- /dev/null +++ b/src/libstd/sync/mpsc/select_tests.rs @@ -0,0 +1,413 @@ +#![allow(unused_imports)] + +/// This file exists to hack around https://github.com/rust-lang/rust/issues/47238 + +use thread; +use 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 af538b75b70..3da73ac0b82 100644 --- a/src/libstd/sync/mpsc/shared.rs +++ b/src/libstd/sync/mpsc/shared.rs @@ -1,4 +1,4 @@ -/// Shared channels +/// Shared channels. /// /// This is the flavor of channels which are not necessarily optimized for any /// particular use case, but are the most general in how they are used. Shared diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 59829db23cb..340dca7ce73 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -335,7 +335,7 @@ impl<T: ?Sized> Mutex<T> { /// Returns a mutable reference to the underlying data. /// /// Since this call borrows the `Mutex` mutably, no actual locking needs to - /// take place---the mutable borrow statically guarantees no locks exist. + /// take place -- the mutable borrow statically guarantees no locks exist. /// /// # Errors /// diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index fcab2ffe144..656389789d7 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -228,7 +228,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 no-op. + /// `call_one_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`. @@ -279,7 +279,7 @@ impl Once { }); } - /// Returns true if some `call_once` call has completed + /// Returns `true` if some `call_once` call has completed /// successfully. Specifically, `is_completed` will return false in /// the following situations: /// * `call_once` was not called at all, @@ -465,7 +465,7 @@ impl<'a> Drop for Finish<'a> { } impl OnceState { - /// Returns whether the associated [`Once`] was poisoned prior to the + /// Returns `true` if the associated [`Once`] was poisoned prior to the /// invocation of the closure passed to [`call_once_force`]. /// /// [`call_once_force`]: struct.Once.html#method.call_once_force diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 7fbe0b8c199..730362e2ac8 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -314,7 +314,7 @@ impl<T: ?Sized> RwLock<T> { /// Determines whether the lock is poisoned. /// /// If another thread is active, the lock can still become poisoned at any - /// time. You should not trust a `false` value for program correctness + /// time. You should not trust a `false` value for program correctness /// without additional synchronization. /// /// # Examples @@ -384,7 +384,7 @@ impl<T: ?Sized> RwLock<T> { /// Returns a mutable reference to the underlying data. /// /// Since this call borrows the `RwLock` mutably, no actual locking needs to - /// take place---the mutable borrow statically guarantees no locks exist. + /// take place -- the mutable borrow statically guarantees no locks exist. /// /// # Errors /// |
