about summary refs log tree commit diff
path: root/src/libstd/sync
diff options
context:
space:
mode:
authorStein Somers <git@steinsomers.be>2019-02-18 00:31:41 +0100
committerStein Somers <git@steinsomers.be>2019-02-18 00:31:41 +0100
commit01bebdf19321a1597f35c2fc2130f1627e944bcf (patch)
tree2c71bc6a77545eacabdc67b1fcaa5f52dd22878c /src/libstd/sync
parent0b9ad6e6fd017837647eed8e5ae824d1f6e278b2 (diff)
parent9a3392e174a432a5f06c1157befc1ce0fae74bec (diff)
downloadrust-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.rs2
-rw-r--r--src/libstd/sync/condvar.rs10
-rw-r--r--src/libstd/sync/mpsc/blocking.rs6
-rw-r--r--src/libstd/sync/mpsc/mod.rs5
-rw-r--r--src/libstd/sync/mpsc/select.rs424
-rw-r--r--src/libstd/sync/mpsc/select_tests.rs413
-rw-r--r--src/libstd/sync/mpsc/shared.rs2
-rw-r--r--src/libstd/sync/mutex.rs2
-rw-r--r--src/libstd/sync/once.rs6
-rw-r--r--src/libstd/sync/rwlock.rs4
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
     ///