]> git.lizzy.rs Git - rust.git/commitdiff
std: Second pass stabilization for `comm`
authorAlex Crichton <alex@alexcrichton.com>
Tue, 23 Dec 2014 19:53:35 +0000 (11:53 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Mon, 29 Dec 2014 20:16:49 +0000 (12:16 -0800)
This commit is a second pass stabilization for the `std::comm` module,
performing the following actions:

* The entire `std::comm` module was moved under `std::sync::mpsc`. This movement
  reflects that channels are just yet another synchronization primitive, and
  they don't necessarily deserve a special place outside of the other
  concurrency primitives that the standard library offers.
* The `send` and `recv` methods have all been removed.
* The `send_opt` and `recv_opt` methods have been renamed to `send` and `recv`.
  This means that all send/receive operations return a `Result` now indicating
  whether the operation was successful or not.
* The error type of `send` is now a `SendError` to implement a custom error
  message and allow for `unwrap()`. The error type contains an `into_inner`
  method to extract the value.
* The error type of `recv` is now `RecvError` for the same reasons as `send`.
* The `TryRecvError` and `TrySendError` types have had public reexports removed
  of their variants and the variant names have been tweaked with enum
  namespacing rules.
* The `Messages` iterator is renamed to `Iter`

This functionality is now all `#[stable]`:

* `Sender`
* `SyncSender`
* `Receiver`
* `std::sync::mpsc`
* `channel`
* `sync_channel`
* `Iter`
* `Sender::send`
* `Sender::clone`
* `SyncSender::send`
* `SyncSender::try_send`
* `SyncSender::clone`
* `Receiver::recv`
* `Receiver::try_recv`
* `Receiver::iter`
* `SendError`
* `RecvError`
* `TrySendError::{mod, Full, Disconnected}`
* `TryRecvError::{mod, Empty, Disconnected}`
* `SendError::into_inner`
* `TrySendError::into_inner`

This is a breaking change due to the modification of where this module is
located, as well as the changing of the semantics of `send` and `recv`. Most
programs just need to rename imports of `std::comm` to `std::sync::mpsc` and
add calls to `unwrap` after a send or a receive operation.

[breaking-change]

118 files changed:
src/etc/licenseck.py
src/liballoc/arc.rs
src/libcollections/bit.rs
src/librustc_driver/lib.rs
src/librustc_trans/back/write.rs
src/librustc_trans/save/mod.rs
src/librustdoc/test.rs
src/libstd/bitflags.rs
src/libstd/c_str.rs
src/libstd/c_vec.rs
src/libstd/collections/hash/map.rs
src/libstd/comm/blocking.rs [deleted file]
src/libstd/comm/mod.rs [deleted file]
src/libstd/comm/mpsc_queue.rs [deleted file]
src/libstd/comm/oneshot.rs [deleted file]
src/libstd/comm/select.rs [deleted file]
src/libstd/comm/shared.rs [deleted file]
src/libstd/comm/spsc_queue.rs [deleted file]
src/libstd/comm/stream.rs [deleted file]
src/libstd/comm/sync.rs [deleted file]
src/libstd/io/buffered.rs
src/libstd/io/comm_adapters.rs
src/libstd/io/mem.rs
src/libstd/io/net/pipe.rs
src/libstd/io/net/tcp.rs
src/libstd/io/net/udp.rs
src/libstd/io/pipe.rs
src/libstd/io/process.rs
src/libstd/io/stdio.rs
src/libstd/io/timer.rs
src/libstd/io/util.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/num/f32.rs
src/libstd/num/f64.rs
src/libstd/os.rs
src/libstd/path/posix.rs
src/libstd/path/windows.rs
src/libstd/rand/os.rs
src/libstd/sync/barrier.rs
src/libstd/sync/condvar.rs
src/libstd/sync/future.rs
src/libstd/sync/mod.rs
src/libstd/sync/mpsc/blocking.rs [new file with mode: 0644]
src/libstd/sync/mpsc/mod.rs [new file with mode: 0644]
src/libstd/sync/mpsc/mpsc_queue.rs [new file with mode: 0644]
src/libstd/sync/mpsc/oneshot.rs [new file with mode: 0644]
src/libstd/sync/mpsc/select.rs [new file with mode: 0644]
src/libstd/sync/mpsc/shared.rs [new file with mode: 0644]
src/libstd/sync/mpsc/spsc_queue.rs [new file with mode: 0644]
src/libstd/sync/mpsc/stream.rs [new file with mode: 0644]
src/libstd/sync/mpsc/sync.rs [new file with mode: 0644]
src/libstd/sync/mutex.rs
src/libstd/sync/once.rs
src/libstd/sync/rwlock.rs
src/libstd/sync/semaphore.rs
src/libstd/sync/task_pool.rs
src/libstd/sys/common/helper_thread.rs
src/libstd/sys/unix/process.rs
src/libstd/sys/unix/timer.rs
src/libstd/thread.rs
src/libstd/thread_local/mod.rs
src/libtest/lib.rs
src/test/auxiliary/cci_capture_clause.rs
src/test/compile-fail/bind-by-move-no-guards.rs
src/test/compile-fail/builtin-superkinds-self-type.rs
src/test/compile-fail/comm-not-freeze-receiver.rs
src/test/compile-fail/comm-not-freeze.rs
src/test/compile-fail/issue-12041.rs
src/test/compile-fail/unsendable-class.rs
src/test/run-pass/bool.rs
src/test/run-pass/builtin-superkinds-capabilities-transitive.rs
src/test/run-pass/builtin-superkinds-capabilities-xc.rs
src/test/run-pass/builtin-superkinds-capabilities.rs
src/test/run-pass/builtin-superkinds-self-type.rs
src/test/run-pass/capturing-logging.rs
src/test/run-pass/cci_capture_clause.rs
src/test/run-pass/closure-bounds-can-capture-chan.rs
src/test/run-pass/comm.rs
src/test/run-pass/core-run-destroy.rs
src/test/run-pass/drop-trait-enum.rs
src/test/run-pass/hashmap-memory.rs
src/test/run-pass/issue-13494.rs
src/test/run-pass/issue-3609.rs
src/test/run-pass/issue-4446.rs
src/test/run-pass/issue-4448.rs
src/test/run-pass/issue-8827.rs
src/test/run-pass/issue-9396.rs
src/test/run-pass/ivec-tag.rs
src/test/run-pass/rust-log-filter.rs
src/test/run-pass/send-resource.rs
src/test/run-pass/send-type-inference.rs
src/test/run-pass/sendable-class.rs
src/test/run-pass/spawn-types.rs
src/test/run-pass/task-comm-0.rs
src/test/run-pass/task-comm-10.rs
src/test/run-pass/task-comm-11.rs
src/test/run-pass/task-comm-13.rs
src/test/run-pass/task-comm-14.rs
src/test/run-pass/task-comm-15.rs
src/test/run-pass/task-comm-16.rs
src/test/run-pass/task-comm-3.rs
src/test/run-pass/task-comm-4.rs
src/test/run-pass/task-comm-5.rs
src/test/run-pass/task-comm-6.rs
src/test/run-pass/task-comm-7.rs
src/test/run-pass/task-comm-9.rs
src/test/run-pass/task-comm-chan-nil.rs
src/test/run-pass/task-spawn-move-and-copy.rs
src/test/run-pass/task-stderr.rs
src/test/run-pass/tcp-accept-stress.rs
src/test/run-pass/tcp-connect-timeouts.rs
src/test/run-pass/tempfile.rs
src/test/run-pass/trait-bounds-in-arc.rs
src/test/run-pass/trivial-message.rs
src/test/run-pass/unique-send-2.rs
src/test/run-pass/unique-send.rs
src/test/run-pass/unwind-resource.rs

index 7669df36b041d9282aea7e22d7b0f771d7332e86..9ac0acc38a73e8b61c47694177aee91c87c95f6e 100644 (file)
@@ -38,8 +38,8 @@ exceptions = [
     "rt/isaac/randport.cpp", # public domain
     "rt/isaac/rand.h", # public domain
     "rt/isaac/standard.h", # public domain
-    "libstd/comm/mpsc_queue.rs", # BSD
-    "libstd/comm/spsc_queue.rs", # BSD
+    "libstd/sync/mpsc/mpsc_queue.rs", # BSD
+    "libstd/sync/mpsc/spsc_queue.rs", # BSD
     "test/bench/shootout-binarytrees.rs", # BSD
     "test/bench/shootout-chameneos-redux.rs", # BSD
     "test/bench/shootout-fannkuch-redux.rs", # BSD
index 3e235caab18ad1431befa20a802419cb497f1c88..b8c7bc74132e47d14468e8f661f551c3a9501e85 100644 (file)
@@ -592,7 +592,7 @@ fn default() -> Arc<T> { Arc::new(Default::default()) }
 #[allow(experimental)]
 mod tests {
     use std::clone::Clone;
-    use std::comm::channel;
+    use std::sync::mpsc::channel;
     use std::mem::drop;
     use std::ops::Drop;
     use std::option::Option;
@@ -628,11 +628,11 @@ fn manually_share_arc() {
         let (tx, rx) = channel();
 
         task::spawn(move || {
-            let arc_v: Arc<Vec<int>> = rx.recv();
+            let arc_v: Arc<Vec<int>> = rx.recv().unwrap();
             assert_eq!((*arc_v)[3], 4);
         });
 
-        tx.send(arc_v.clone());
+        tx.send(arc_v.clone()).unwrap();
 
         assert_eq!((*arc_v)[2], 3);
         assert_eq!((*arc_v)[4], 5);
index e8bd5e76eb7f01c0f5c3b415fe75a1977c81902e..fe3267b6c35d91527e88a5c7acfd636d7ed4cba0 100644 (file)
@@ -2452,7 +2452,7 @@ fn test_bitv_extend() {
 
 #[cfg(test)]
 mod bitv_bench {
-    use std::prelude::*;
+    use std::prelude::v1::*;
     use std::rand;
     use std::rand::Rng;
     use std::u32;
@@ -2947,7 +2947,7 @@ fn test_bitv_clone() {
 
 #[cfg(test)]
 mod bitv_set_bench {
-    use std::prelude::*;
+    use std::prelude::v1::*;
     use std::rand;
     use std::rand::Rng;
     use std::u32;
index 07a4bec4bf89808ee7662b26595082c615f6ecb8..8b716a8431d886263b6ddc3b99235dd7df9acac3 100644 (file)
 
 use std::any::AnyRefExt;
 use std::cmp::Ordering::Equal;
-use std::comm::channel;
 use std::io;
 use std::iter::repeat;
 use std::os;
+use std::sync::mpsc::channel;
 use std::thread;
 
 use rustc::session::early_error;
index 3a40430beae65fe866d1e9d2ed47e53d4518223c..55e6dfaebcd5110cc704fa4204b338e7b8e05403 100644 (file)
@@ -23,7 +23,6 @@
 use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
 
 use std::c_str::{ToCStr, CString};
-use std::comm::channel;
 use std::io::Command;
 use std::io::fs;
 use std::iter::Unfold;
@@ -31,6 +30,7 @@
 use std::str;
 use std::mem;
 use std::sync::{Arc, Mutex};
+use std::sync::mpsc::channel;
 use std::thread;
 use libc::{c_uint, c_int, c_void};
 
@@ -929,13 +929,13 @@ fn run_work_multithreaded(sess: &Session,
                 }
             }
 
-            tx.take().unwrap().send(());
+            tx.take().unwrap().send(()).unwrap();
         }).detach();
     }
 
     let mut panicked = false;
     for rx in futures.into_iter() {
-        match rx.recv_opt() {
+        match rx.recv() {
             Ok(()) => {},
             Err(_) => {
                 panicked = true;
index f491bc84b62c476d158e71bc714d2c691b23ed27..e105a1f6a95f3c50d8cfa77ec1853171eb46f65f 100644 (file)
@@ -1203,8 +1203,7 @@ fn visit_view_item(&mut self, i: &ast::ViewItem) {
                         let glob_map = &self.analysis.glob_map;
                         let glob_map = glob_map.as_ref().unwrap();
                         if glob_map.contains_key(&id) {
-                            let names = glob_map.index(&id);
-                            for n in names.iter() {
+                            for n in glob_map[id].iter() {
                                 if name_string.len() > 0 {
                                     name_string.push_str(", ");
                                 }
index a9f30ee5ef9ed0d2336a97d2cb1f772f3d7f1776..a50bfbde0fea276c45f9692a0b555ec9225886a7 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::cell::RefCell;
-use std::comm::channel;
+use std::sync::mpsc::channel;
 use std::dynamic_lib::DynamicLibrary;
 use std::io::{Command, TempDir};
 use std::io;
index 1826ad3dc31548c328ff93aac45141c4b09030f8..4ec329de600e1457d83b6b453491e638884f427a 100644 (file)
@@ -273,7 +273,6 @@ fn not(self) -> $BitFlags {
 mod tests {
     use hash;
     use option::Option::{Some, None};
-    use ops::{BitOr, BitAnd, BitXor, Sub, Not};
 
     bitflags! {
         #[doc = "> The first principle is that you must not fool yourself â€” and"]
index fa0d8fa9bd5a1e5aa299cc5821fa8b32bb062b8f..d096903f9c47d1c0a050a7a27ee07e70a262af4b 100644 (file)
@@ -621,7 +621,7 @@ fn test_vec_to_c_str() {
     #[test]
     fn test_unwrap() {
         let c_str = "hello".to_c_str();
-        unsafe { libc::free(c_str.unwrap() as *mut libc::c_void) }
+        unsafe { libc::free(c_str.into_inner() as *mut libc::c_void) }
     }
 
     #[test]
index d0293aa4a1c979023eb417db73fcb07e9cc6fc18..a80659ed937e5c25edfe3671b047659e0909808a 100644 (file)
@@ -228,7 +228,7 @@ fn test_unwrap() {
             let cv = CVec::new_with_dtor(1 as *mut int,
                                          0,
                                          move|:| panic!("Don't run this destructor!"));
-            let p = cv.unwrap();
+            let p = cv.into_inner();
             assert_eq!(p, 1 as *mut int);
         }
     }
index e7918d605cbaef9d2cae581f0a1c036c5f64b683..8585b4ecf52ade988a0cc65740b371fa74a39333 100644 (file)
@@ -1485,6 +1485,7 @@ mod test_map {
 
     struct KindaIntLike(int);
 
+    #[allow(deprecated)]
     impl Equiv<int> for KindaIntLike {
         fn equiv(&self, other: &int) -> bool {
             let KindaIntLike(this) = *self;
@@ -1812,7 +1813,7 @@ fn test_pop() {
     }
 
     #[test]
-    #[allow(experimental)]
+    #[allow(deprecated)]
     fn test_pop_equiv() {
         let mut m = HashMap::new();
         m.insert(1i, 2i);
diff --git a/src/libstd/comm/blocking.rs b/src/libstd/comm/blocking.rs
deleted file mode 100644 (file)
index 412b716..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Generic support for building blocking abstractions.
-
-use thread::Thread;
-use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Ordering};
-use sync::Arc;
-use kinds::{Sync, Send};
-use kinds::marker::{NoSend, NoSync};
-use mem;
-use clone::Clone;
-
-struct Inner {
-    thread: Thread,
-    woken: AtomicBool,
-}
-
-unsafe impl Send for Inner {}
-unsafe impl Sync for Inner {}
-
-#[deriving(Clone)]
-pub struct SignalToken {
-    inner: Arc<Inner>,
-}
-
-pub struct WaitToken {
-    inner: Arc<Inner>,
-    no_send: NoSend,
-    no_sync: NoSync,
-}
-
-pub fn tokens() -> (WaitToken, SignalToken) {
-    let inner = Arc::new(Inner {
-        thread: Thread::current(),
-        woken: INIT_ATOMIC_BOOL,
-    });
-    let wait_token = WaitToken {
-        inner: inner.clone(),
-        no_send: NoSend,
-        no_sync: NoSync,
-    };
-    let signal_token = SignalToken {
-        inner: inner
-    };
-    (wait_token, signal_token)
-}
-
-impl SignalToken {
-    pub fn signal(&self) -> bool {
-        let wake = !self.inner.woken.compare_and_swap(false, true, Ordering::SeqCst);
-        if wake {
-            self.inner.thread.unpark();
-        }
-        wake
-    }
-
-    /// Convert to an unsafe uint value. Useful for storing in a pipe's state
-    /// flag.
-    #[inline]
-    pub unsafe fn cast_to_uint(self) -> uint {
-        mem::transmute(self.inner)
-    }
-
-    /// Convert from an unsafe uint value. Useful for retrieving a pipe's state
-    /// flag.
-    #[inline]
-    pub unsafe fn cast_from_uint(signal_ptr: uint) -> SignalToken {
-        SignalToken { inner: mem::transmute(signal_ptr) }
-    }
-
-}
-
-impl WaitToken {
-    pub fn wait(self) {
-        while !self.inner.woken.load(Ordering::SeqCst) {
-            Thread::park()
-        }
-    }
-}
diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs
deleted file mode 100644 (file)
index de7f3d0..0000000
+++ /dev/null
@@ -1,2133 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Communication primitives for concurrent tasks
-//!
-//! Rust makes it very difficult to share data among tasks to prevent race
-//! conditions and to improve parallelism, but there is often a need for
-//! communication between concurrent tasks. The primitives defined in this
-//! module are the building blocks for synchronization in rust.
-//!
-//! This module provides message-based communication over channels, concretely
-//! defined among three types:
-//!
-//! * `Sender`
-//! * `SyncSender`
-//! * `Receiver`
-//!
-//! A `Sender` or `SyncSender` is used to send data to a `Receiver`. Both
-//! senders are clone-able such that many tasks can send simultaneously to one
-//! receiver.  These channels are *task blocking*, not *thread blocking*. This
-//! means that if one task is blocked on a channel, other tasks can continue to
-//! make progress.
-//!
-//! Rust channels come in one of two flavors:
-//!
-//! 1. An asynchronous, infinitely buffered channel. The `channel()` function
-//!    will return a `(Sender, Receiver)` tuple where all sends will be
-//!    **asynchronous** (they never block). The channel conceptually has an
-//!    infinite buffer.
-//!
-//! 2. A synchronous, bounded channel. The `sync_channel()` function will return
-//!    a `(SyncSender, Receiver)` tuple where the storage for pending messages
-//!    is a pre-allocated buffer of a fixed size. All sends will be
-//!    **synchronous** by blocking until there is buffer space available. Note
-//!    that a bound of 0 is allowed, causing the channel to become a
-//!    "rendezvous" channel where each sender atomically hands off a message to
-//!    a receiver.
-//!
-//! ## Panic Propagation
-//!
-//! In addition to being a core primitive for communicating in rust, channels
-//! are the points at which panics are propagated among tasks.  Whenever the one
-//! half of channel is closed, the other half will have its next operation
-//! `panic!`. The purpose of this is to allow propagation of panics among tasks
-//! that are linked to one another via channels.
-//!
-//! There are methods on both of senders and receivers to perform their
-//! respective operations without panicking, however.
-//!
-//! # Example
-//!
-//! Simple usage:
-//!
-//! ```
-//! use std::thread::Thread;
-//! use std::comm::channel;
-//!
-//! // Create a simple streaming channel
-//! let (tx, rx) = channel();
-//! Thread::spawn(move|| {
-//!     tx.send(10i);
-//! }).detach();
-//! assert_eq!(rx.recv(), 10i);
-//! ```
-//!
-//! Shared usage:
-//!
-//! ```
-//! use std::thread::Thread;
-//! use std::comm::channel;
-//!
-//! // Create a shared channel that can be sent along from many threads
-//! // where tx is the sending half (tx for transmission), and rx is the receiving
-//! // half (rx for receiving).
-//! let (tx, rx) = channel();
-//! for i in range(0i, 10i) {
-//!     let tx = tx.clone();
-//!     Thread::spawn(move|| {
-//!         tx.send(i);
-//!     }).detach()
-//! }
-//!
-//! for _ in range(0i, 10i) {
-//!     let j = rx.recv();
-//!     assert!(0 <= j && j < 10);
-//! }
-//! ```
-//!
-//! Propagating panics:
-//!
-//! ```should_fail
-//! use std::comm::channel;
-//!
-//! // The call to recv() will panic!() because the channel has already hung
-//! // up (or been deallocated)
-//! let (tx, rx) = channel::<int>();
-//! drop(tx);
-//! rx.recv();
-//! ```
-//!
-//! Synchronous channels:
-//!
-//! ```
-//! use std::thread::Thread;
-//! use std::comm::sync_channel;
-//!
-//! let (tx, rx) = sync_channel::<int>(0);
-//! Thread::spawn(move|| {
-//!     // This will wait for the parent task to start receiving
-//!     tx.send(53);
-//! }).detach();
-//! rx.recv();
-//! ```
-//!
-//! Reading from a channel with a timeout requires to use a Timer together
-//! with the channel. You can use the select! macro to select either and
-//! handle the timeout case. This first example will break out of the loop
-//! after 10 seconds no matter what:
-//!
-//! ```no_run
-//! use std::comm::channel;
-//! use std::io::timer::Timer;
-//! use std::time::Duration;
-//!
-//! let (tx, rx) = channel::<int>();
-//! let mut timer = Timer::new().unwrap();
-//! let timeout = timer.oneshot(Duration::seconds(10));
-//!
-//! loop {
-//!     select! {
-//!         val = rx.recv() => println!("Received {}", val),
-//!         () = timeout.recv() => {
-//!             println!("timed out, total time was more than 10 seconds");
-//!             break;
-//!         }
-//!     }
-//! }
-//! ```
-//!
-//! This second example is more costly since it allocates a new timer every
-//! time a message is received, but it allows you to timeout after the channel
-//! has been inactive for 5 seconds:
-//!
-//! ```no_run
-//! use std::comm::channel;
-//! use std::io::timer::Timer;
-//! use std::time::Duration;
-//!
-//! let (tx, rx) = channel::<int>();
-//! let mut timer = Timer::new().unwrap();
-//!
-//! loop {
-//!     let timeout = timer.oneshot(Duration::seconds(5));
-//!
-//!     select! {
-//!         val = rx.recv() => println!("Received {}", val),
-//!         () = timeout.recv() => {
-//!             println!("timed out, no message received in 5 seconds");
-//!             break;
-//!         }
-//!     }
-//! }
-//! ```
-
-// A description of how Rust's channel implementation works
-//
-// Channels are supposed to be the basic building block for all other
-// concurrent primitives that are used in Rust. As a result, the channel type
-// needs to be highly optimized, flexible, and broad enough for use everywhere.
-//
-// The choice of implementation of all channels is to be built on lock-free data
-// structures. The channels themselves are then consequently also lock-free data
-// structures. As always with lock-free code, this is a very "here be dragons"
-// territory, especially because I'm unaware of any academic papers that have
-// gone into great length about channels of these flavors.
-//
-// ## Flavors of channels
-//
-// From the perspective of a consumer of this library, there is only one flavor
-// of channel. This channel can be used as a stream and cloned to allow multiple
-// senders. Under the hood, however, there are actually three flavors of
-// channels in play.
-//
-// * Oneshots - these channels are highly optimized for the one-send use case.
-//              They contain as few atomics as possible and involve one and
-//              exactly one allocation.
-// * Streams - these channels are optimized for the non-shared use case. They
-//             use a different concurrent queue that is more tailored for this
-//             use case. The initial allocation of this flavor of channel is not
-//             optimized.
-// * Shared - this is the most general form of channel that this module offers,
-//            a channel with multiple senders. This type is as optimized as it
-//            can be, but the previous two types mentioned are much faster for
-//            their use-cases.
-//
-// ## Concurrent queues
-//
-// The basic idea of Rust's Sender/Receiver types is that send() never blocks, but
-// recv() obviously blocks. This means that under the hood there must be some
-// shared and concurrent queue holding all of the actual data.
-//
-// With two flavors of channels, two flavors of queues are also used. We have
-// chosen to use queues from a well-known author that are abbreviated as SPSC
-// and MPSC (single producer, single consumer and multiple producer, single
-// consumer). SPSC queues are used for streams while MPSC queues are used for
-// shared channels.
-//
-// ### SPSC optimizations
-//
-// The SPSC queue found online is essentially a linked list of nodes where one
-// half of the nodes are the "queue of data" and the other half of nodes are a
-// cache of unused nodes. The unused nodes are used such that an allocation is
-// not required on every push() and a free doesn't need to happen on every
-// pop().
-//
-// As found online, however, the cache of nodes is of an infinite size. This
-// means that if a channel at one point in its life had 50k items in the queue,
-// then the queue will always have the capacity for 50k items. I believed that
-// this was an unnecessary limitation of the implementation, so I have altered
-// the queue to optionally have a bound on the cache size.
-//
-// By default, streams will have an unbounded SPSC queue with a small-ish cache
-// size. The hope is that the cache is still large enough to have very fast
-// send() operations while not too large such that millions of channels can
-// coexist at once.
-//
-// ### MPSC optimizations
-//
-// Right now the MPSC queue has not been optimized. Like the SPSC queue, it uses
-// a linked list under the hood to earn its unboundedness, but I have not put
-// forth much effort into having a cache of nodes similar to the SPSC queue.
-//
-// For now, I believe that this is "ok" because shared channels are not the most
-// common type, but soon we may wish to revisit this queue choice and determine
-// another candidate for backend storage of shared channels.
-//
-// ## Overview of the Implementation
-//
-// Now that there's a little background on the concurrent queues used, it's
-// worth going into much more detail about the channels themselves. The basic
-// pseudocode for a send/recv are:
-//
-//
-//      send(t)                             recv()
-//        queue.push(t)                       return if queue.pop()
-//        if increment() == -1                deschedule {
-//          wakeup()                            if decrement() > 0
-//                                                cancel_deschedule()
-//                                            }
-//                                            queue.pop()
-//
-// As mentioned before, there are no locks in this implementation, only atomic
-// instructions are used.
-//
-// ### The internal atomic counter
-//
-// Every channel has a shared counter with each half to keep track of the size
-// of the queue. This counter is used to abort descheduling by the receiver and
-// to know when to wake up on the sending side.
-//
-// As seen in the pseudocode, senders will increment this count and receivers
-// will decrement the count. The theory behind this is that if a sender sees a
-// -1 count, it will wake up the receiver, and if the receiver sees a 1+ count,
-// then it doesn't need to block.
-//
-// The recv() method has a beginning call to pop(), and if successful, it needs
-// to decrement the count. It is a crucial implementation detail that this
-// decrement does *not* happen to the shared counter. If this were the case,
-// then it would be possible for the counter to be very negative when there were
-// no receivers waiting, in which case the senders would have to determine when
-// it was actually appropriate to wake up a receiver.
-//
-// Instead, the "steal count" is kept track of separately (not atomically
-// because it's only used by receivers), and then the decrement() call when
-// descheduling will lump in all of the recent steals into one large decrement.
-//
-// The implication of this is that if a sender sees a -1 count, then there's
-// guaranteed to be a waiter waiting!
-//
-// ## Native Implementation
-//
-// A major goal of these channels is to work seamlessly on and off the runtime.
-// All of the previous race conditions have been worded in terms of
-// scheduler-isms (which is obviously not available without the runtime).
-//
-// For now, native usage of channels (off the runtime) will fall back onto
-// mutexes/cond vars for descheduling/atomic decisions. The no-contention path
-// is still entirely lock-free, the "deschedule" blocks above are surrounded by
-// a mutex and the "wakeup" blocks involve grabbing a mutex and signaling on a
-// condition variable.
-//
-// ## Select
-//
-// Being able to support selection over channels has greatly influenced this
-// design, and not only does selection need to work inside the runtime, but also
-// outside the runtime.
-//
-// The implementation is fairly straightforward. The goal of select() is not to
-// return some data, but only to return which channel can receive data without
-// blocking. The implementation is essentially the entire blocking procedure
-// followed by an increment as soon as its woken up. The cancellation procedure
-// involves an increment and swapping out of to_wake to acquire ownership of the
-// task to unblock.
-//
-// Sadly this current implementation requires multiple allocations, so I have
-// seen the throughput of select() be much worse than it should be. I do not
-// believe that there is anything fundamental that needs to change about these
-// channels, however, in order to support a more efficient select().
-//
-// # Conclusion
-//
-// And now that you've seen all the races that I found and attempted to fix,
-// here's the code for you to find some more!
-
-use core::prelude::*;
-
-pub use self::TryRecvError::*;
-pub use self::TrySendError::*;
-use self::Flavor::*;
-
-use alloc::arc::Arc;
-use core::kinds;
-use core::kinds::marker;
-use core::mem;
-use core::cell::UnsafeCell;
-
-pub use self::select::{Select, Handle};
-use self::select::StartResult;
-use self::select::StartResult::*;
-use self::blocking::SignalToken;
-
-mod blocking;
-mod oneshot;
-mod select;
-mod shared;
-mod stream;
-mod sync;
-mod mpsc_queue;
-mod spsc_queue;
-
-/// The receiving-half of Rust's channel type. This half can only be owned by
-/// one task
-#[unstable]
-pub struct Receiver<T> {
-    inner: UnsafeCell<Flavor<T>>,
-}
-
-// The receiver port can be sent from place to place, so long as it
-// is not used to receive non-sendable things.
-unsafe impl<T:Send> Send for Receiver<T> { }
-
-/// An iterator over messages on a receiver, this iterator will block
-/// whenever `next` is called, waiting for a new message, and `None` will be
-/// returned when the corresponding channel has hung up.
-#[unstable]
-pub struct Messages<'a, T:'a> {
-    rx: &'a Receiver<T>
-}
-
-/// The sending-half of Rust's asynchronous channel type. This half can only be
-/// owned by one task, but it can be cloned to send to other tasks.
-#[unstable]
-pub struct Sender<T> {
-    inner: UnsafeCell<Flavor<T>>,
-}
-
-// The send port can be sent from place to place, so long as it
-// is not used to send non-sendable things.
-unsafe impl<T:Send> Send for Sender<T> { }
-
-/// The sending-half of Rust's synchronous channel type. This half can only be
-/// owned by one task, but it can be cloned to send to other tasks.
-#[unstable = "this type may be renamed, but it will always exist"]
-pub struct SyncSender<T> {
-    inner: Arc<RacyCell<sync::Packet<T>>>,
-    // can't share in an arc
-    _marker: marker::NoSync,
-}
-
-/// This enumeration is the list of the possible reasons that try_recv could not
-/// return data when called.
-#[deriving(PartialEq, Clone, Copy, Show)]
-#[experimental = "this is likely to be removed in changing try_recv()"]
-pub enum TryRecvError {
-    /// This channel is currently empty, but the sender(s) have not yet
-    /// disconnected, so data may yet become available.
-    Empty,
-    /// This channel's sending half has become disconnected, and there will
-    /// never be any more data received on this channel
-    Disconnected,
-}
-
-/// This enumeration is the list of the possible error outcomes for the
-/// `SyncSender::try_send` method.
-#[deriving(PartialEq, Clone, Show)]
-#[experimental = "this is likely to be removed in changing try_send()"]
-pub enum TrySendError<T> {
-    /// The data could not be sent on the channel because it would require that
-    /// the callee block to send the data.
-    ///
-    /// If this is a buffered channel, then the buffer is full at this time. If
-    /// this is not a buffered channel, then there is no receiver available to
-    /// acquire the data.
-    Full(T),
-    /// This channel's receiving half has disconnected, so the data could not be
-    /// sent. The data is returned back to the callee in this case.
-    RecvDisconnected(T),
-}
-
-enum Flavor<T> {
-    Oneshot(Arc<RacyCell<oneshot::Packet<T>>>),
-    Stream(Arc<RacyCell<stream::Packet<T>>>),
-    Shared(Arc<RacyCell<shared::Packet<T>>>),
-    Sync(Arc<RacyCell<sync::Packet<T>>>),
-}
-
-#[doc(hidden)]
-trait UnsafeFlavor<T> {
-    fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>>;
-    unsafe fn inner_mut<'a>(&'a self) -> &'a mut Flavor<T> {
-        &mut *self.inner_unsafe().get()
-    }
-    unsafe fn inner<'a>(&'a self) -> &'a Flavor<T> {
-        &*self.inner_unsafe().get()
-    }
-}
-impl<T> UnsafeFlavor<T> for Sender<T> {
-    fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
-        &self.inner
-    }
-}
-impl<T> UnsafeFlavor<T> for Receiver<T> {
-    fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
-        &self.inner
-    }
-}
-
-/// Creates a new asynchronous channel, returning the sender/receiver halves.
-///
-/// All data sent on the sender will become available on the receiver, and no
-/// send will block the calling task (this channel has an "infinite buffer").
-///
-/// # Example
-///
-/// ```
-/// use std::comm::channel;
-/// use std::thread::Thread;
-///
-/// // tx is is the sending half (tx for transmission), and rx is the receiving
-/// // half (rx for receiving).
-/// let (tx, rx) = channel();
-///
-/// // Spawn off an expensive computation
-/// Thread::spawn(move|| {
-/// #   fn expensive_computation() {}
-///     tx.send(expensive_computation());
-/// }).detach();
-///
-/// // Do some useful work for awhile
-///
-/// // Let's see what that answer was
-/// println!("{}", rx.recv());
-/// ```
-#[unstable]
-pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
-    let a = Arc::new(RacyCell::new(oneshot::Packet::new()));
-    (Sender::new(Oneshot(a.clone())), Receiver::new(Oneshot(a)))
-}
-
-/// Creates a new synchronous, bounded channel.
-///
-/// Like asynchronous channels, the `Receiver` will block until a message
-/// becomes available. These channels differ greatly in the semantics of the
-/// sender from asynchronous channels, however.
-///
-/// This channel has an internal buffer on which messages will be queued. When
-/// the internal buffer becomes full, future sends will *block* waiting for the
-/// buffer to open up. Note that a buffer size of 0 is valid, in which case this
-/// becomes  "rendezvous channel" where each send will not return until a recv
-/// is paired with it.
-///
-/// As with asynchronous channels, all senders will panic in `send` if the
-/// `Receiver` has been destroyed.
-///
-/// # Example
-///
-/// ```
-/// use std::comm::sync_channel;
-/// use std::thread::Thread;
-///
-/// let (tx, rx) = sync_channel(1);
-///
-/// // this returns immediately
-/// tx.send(1i);
-///
-/// Thread::spawn(move|| {
-///     // this will block until the previous message has been received
-///     tx.send(2i);
-/// }).detach();
-///
-/// assert_eq!(rx.recv(), 1i);
-/// assert_eq!(rx.recv(), 2i);
-/// ```
-#[unstable = "this function may be renamed to more accurately reflect the type \
-              of channel that is is creating"]
-pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
-    let a = Arc::new(RacyCell::new(sync::Packet::new(bound)));
-    (SyncSender::new(a.clone()), Receiver::new(Sync(a)))
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Sender
-////////////////////////////////////////////////////////////////////////////////
-
-impl<T: Send> Sender<T> {
-    fn new(inner: Flavor<T>) -> Sender<T> {
-        Sender {
-            inner: UnsafeCell::new(inner),
-        }
-    }
-
-    /// Sends a value along this channel to be received by the corresponding
-    /// receiver.
-    ///
-    /// Rust channels are infinitely buffered so this method will never block.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if the other end of the channel has hung up.
-    /// This means that if the corresponding receiver has fallen out of scope,
-    /// this function will trigger a panic message saying that a message is
-    /// being sent on a closed channel.
-    ///
-    /// Note that if this function does *not* panic, it does not mean that the
-    /// data will be successfully received. All sends are placed into a queue,
-    /// so it is possible for a send to succeed (the other end is alive), but
-    /// then the other end could immediately disconnect.
-    ///
-    /// The purpose of this functionality is to propagate panics among tasks.
-    /// If a panic is not desired, then consider using the `send_opt` method
-    #[experimental = "this function is being considered candidate for removal \
-                      to adhere to the general guidelines of rust"]
-    pub fn send(&self, t: T) {
-        if self.send_opt(t).is_err() {
-            panic!("sending on a closed channel");
-        }
-    }
-
-    /// Attempts to send a value on this channel, returning it back if it could
-    /// not be sent.
-    ///
-    /// A successful send occurs when it is determined that the other end of
-    /// the channel has not hung up already. An unsuccessful send would be one
-    /// 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
-    /// hang up immediately after this function returns `Ok`.
-    ///
-    /// Like `send`, this method will never block.
-    ///
-    /// # Panics
-    ///
-    /// This method will never panic, it will return the message back to the
-    /// caller if the other end is disconnected
-    ///
-    /// # Example
-    ///
-    /// ```
-    /// use std::comm::channel;
-    ///
-    /// let (tx, rx) = channel();
-    ///
-    /// // This send is always successful
-    /// assert_eq!(tx.send_opt(1i), Ok(()));
-    ///
-    /// // This send will fail because the receiver is gone
-    /// drop(rx);
-    /// assert_eq!(tx.send_opt(1i), Err(1));
-    /// ```
-    #[unstable = "this function may be renamed to send() in the future"]
-    pub fn send_opt(&self, t: T) -> Result<(), T> {
-        let (new_inner, ret) = match *unsafe { self.inner() } {
-            Oneshot(ref p) => {
-                unsafe {
-                    let p = p.get();
-                    if !(*p).sent() {
-                        return (*p).send(t);
-                    } else {
-                        let a =
-                            Arc::new(RacyCell::new(stream::Packet::new()));
-                        match (*p).upgrade(Receiver::new(Stream(a.clone()))) {
-                            oneshot::UpSuccess => {
-                                let ret = (*a.get()).send(t);
-                                (a, ret)
-                            }
-                            oneshot::UpDisconnected => (a, Err(t)),
-                            oneshot::UpWoke(token) => {
-                                // This send cannot panic because the thread is
-                                // asleep (we're looking at it), so the receiver
-                                // can't go away.
-                                (*a.get()).send(t).ok().unwrap();
-                                token.signal();
-                                (a, Ok(()))
-                            }
-                        }
-                    }
-                }
-            }
-            Stream(ref p) => return unsafe { (*p.get()).send(t) },
-            Shared(ref p) => return unsafe { (*p.get()).send(t) },
-            Sync(..) => unreachable!(),
-        };
-
-        unsafe {
-            let tmp = Sender::new(Stream(new_inner));
-            mem::swap(self.inner_mut(), tmp.inner_mut());
-        }
-        return ret;
-    }
-}
-
-#[stable]
-impl<T: Send> Clone for Sender<T> {
-    fn clone(&self) -> Sender<T> {
-        let (packet, sleeper, guard) = match *unsafe { self.inner() } {
-            Oneshot(ref p) => {
-                let a = Arc::new(RacyCell::new(shared::Packet::new()));
-                unsafe {
-                    let guard = (*a.get()).postinit_lock();
-                    match (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) {
-                        oneshot::UpSuccess |
-                        oneshot::UpDisconnected => (a, None, guard),
-                        oneshot::UpWoke(task) => (a, Some(task), guard)
-                    }
-                }
-            }
-            Stream(ref p) => {
-                let a = Arc::new(RacyCell::new(shared::Packet::new()));
-                unsafe {
-                    let guard = (*a.get()).postinit_lock();
-                    match (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) {
-                        stream::UpSuccess |
-                        stream::UpDisconnected => (a, None, guard),
-                        stream::UpWoke(task) => (a, Some(task), guard),
-                    }
-                }
-            }
-            Shared(ref p) => {
-                unsafe { (*p.get()).clone_chan(); }
-                return Sender::new(Shared(p.clone()));
-            }
-            Sync(..) => unreachable!(),
-        };
-
-        unsafe {
-            (*packet.get()).inherit_blocker(sleeper, guard);
-
-            let tmp = Sender::new(Shared(packet.clone()));
-            mem::swap(self.inner_mut(), tmp.inner_mut());
-        }
-        Sender::new(Shared(packet))
-    }
-}
-
-#[unsafe_destructor]
-impl<T: Send> Drop for Sender<T> {
-    fn drop(&mut self) {
-        match *unsafe { self.inner_mut() } {
-            Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); },
-            Stream(ref mut p) => unsafe { (*p.get()).drop_chan(); },
-            Shared(ref mut p) => unsafe { (*p.get()).drop_chan(); },
-            Sync(..) => unreachable!(),
-        }
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// SyncSender
-////////////////////////////////////////////////////////////////////////////////
-
-impl<T: Send> SyncSender<T> {
-    fn new(inner: Arc<RacyCell<sync::Packet<T>>>) -> SyncSender<T> {
-        SyncSender { inner: inner, _marker: marker::NoSync }
-    }
-
-    /// Sends a value on this synchronous channel.
-    ///
-    /// This function will *block* until space in the internal buffer becomes
-    /// available or a receiver is available to hand off the message to.
-    ///
-    /// Note that a successful send does *not* guarantee that the receiver will
-    /// ever see the data if there is a buffer on this channel. Messages may be
-    /// enqueued in the internal buffer for the receiver to receive at a later
-    /// time. If the buffer size is 0, however, it can be guaranteed that the
-    /// receiver has indeed received the data if this function returns success.
-    ///
-    /// # Panics
-    ///
-    /// Similarly to `Sender::send`, this function will panic if the
-    /// corresponding `Receiver` for this channel has disconnected. This
-    /// behavior is used to propagate panics among tasks.
-    ///
-    /// If a panic is not desired, you can achieve the same semantics with the
-    /// `SyncSender::send_opt` method which will not panic if the receiver
-    /// disconnects.
-    #[experimental = "this function is being considered candidate for removal \
-                      to adhere to the general guidelines of rust"]
-    pub fn send(&self, t: T) {
-        if self.send_opt(t).is_err() {
-            panic!("sending on a closed channel");
-        }
-    }
-
-    /// Send a value on a channel, returning it back if the receiver
-    /// disconnected
-    ///
-    /// This method will *block* to send the value `t` on the channel, but if
-    /// the value could not be sent due to the receiver disconnecting, the value
-    /// is returned back to the callee. This function is similar to `try_send`,
-    /// except that it will block if the channel is currently full.
-    ///
-    /// # Panics
-    ///
-    /// This function cannot panic.
-    #[unstable = "this function may be renamed to send() in the future"]
-    pub fn send_opt(&self, t: T) -> Result<(), T> {
-        unsafe { (*self.inner.get()).send(t) }
-    }
-
-    /// Attempts to send a value on this channel without blocking.
-    ///
-    /// This method differs from `send_opt` by returning immediately if the
-    /// channel's buffer is full or no receiver is waiting to acquire some
-    /// data. Compared with `send_opt`, this function has two failure cases
-    /// instead of one (one for disconnection, one for a full buffer).
-    ///
-    /// See `SyncSender::send` for notes about guarantees of whether the
-    /// receiver has received the data or not if this function is successful.
-    ///
-    /// # Panics
-    ///
-    /// This function cannot panic
-    #[unstable = "the return type of this function is candidate for \
-                  modification"]
-    pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
-        unsafe { (*self.inner.get()).try_send(t) }
-    }
-}
-
-#[stable]
-impl<T: Send> Clone for SyncSender<T> {
-    fn clone(&self) -> SyncSender<T> {
-        unsafe { (*self.inner.get()).clone_chan(); }
-        return SyncSender::new(self.inner.clone());
-    }
-}
-
-#[unsafe_destructor]
-impl<T: Send> Drop for SyncSender<T> {
-    fn drop(&mut self) {
-        unsafe { (*self.inner.get()).drop_chan(); }
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Receiver
-////////////////////////////////////////////////////////////////////////////////
-
-impl<T: Send> Receiver<T> {
-    fn new(inner: Flavor<T>) -> Receiver<T> {
-        Receiver { inner: UnsafeCell::new(inner) }
-    }
-
-    /// Blocks waiting for a value on this receiver
-    ///
-    /// This function will block if necessary to wait for a corresponding send
-    /// on the channel from its paired `Sender` structure. This receiver will
-    /// be woken up when data is ready, and the data will be returned.
-    ///
-    /// # Panics
-    ///
-    /// Similar to channels, this method will trigger a task panic if the
-    /// other end of the channel has hung up (been deallocated). The purpose of
-    /// this is to propagate panics among tasks.
-    ///
-    /// If a panic is not desired, then there are two options:
-    ///
-    /// * If blocking is still desired, the `recv_opt` method will return `None`
-    ///   when the other end hangs up
-    ///
-    /// * If blocking is not desired, then the `try_recv` method will attempt to
-    ///   peek at a value on this receiver.
-    #[experimental = "this function is being considered candidate for removal \
-                      to adhere to the general guidelines of rust"]
-    pub fn recv(&self) -> T {
-        match self.recv_opt() {
-            Ok(t) => t,
-            Err(()) => panic!("receiving on a closed channel"),
-        }
-    }
-
-    /// Attempts to return a pending value on this receiver without blocking
-    ///
-    /// This method will never block the caller in order to wait for data to
-    /// become available. Instead, this will always return immediately with a
-    /// possible option of pending data on the channel.
-    ///
-    /// This is useful for a flavor of "optimistic check" before deciding to
-    /// block on a receiver.
-    ///
-    /// # Panics
-    ///
-    /// This function cannot panic.
-    #[unstable = "the return type of this function may be altered"]
-    pub fn try_recv(&self) -> Result<T, TryRecvError> {
-        loop {
-            let new_port = match *unsafe { self.inner() } {
-                Oneshot(ref p) => {
-                    match unsafe { (*p.get()).try_recv() } {
-                        Ok(t) => return Ok(t),
-                        Err(oneshot::Empty) => return Err(Empty),
-                        Err(oneshot::Disconnected) => return Err(Disconnected),
-                        Err(oneshot::Upgraded(rx)) => rx,
-                    }
-                }
-                Stream(ref p) => {
-                    match unsafe { (*p.get()).try_recv() } {
-                        Ok(t) => return Ok(t),
-                        Err(stream::Empty) => return Err(Empty),
-                        Err(stream::Disconnected) => return Err(Disconnected),
-                        Err(stream::Upgraded(rx)) => rx,
-                    }
-                }
-                Shared(ref p) => {
-                    match unsafe { (*p.get()).try_recv() } {
-                        Ok(t) => return Ok(t),
-                        Err(shared::Empty) => return Err(Empty),
-                        Err(shared::Disconnected) => return Err(Disconnected),
-                    }
-                }
-                Sync(ref p) => {
-                    match unsafe { (*p.get()).try_recv() } {
-                        Ok(t) => return Ok(t),
-                        Err(sync::Empty) => return Err(Empty),
-                        Err(sync::Disconnected) => return Err(Disconnected),
-                    }
-                }
-            };
-            unsafe {
-                mem::swap(self.inner_mut(),
-                          new_port.inner_mut());
-            }
-        }
-    }
-
-    /// Attempt to wait for a value on this receiver, but does not panic if the
-    /// corresponding channel has hung up.
-    ///
-    /// This implementation of iterators for ports will always block if there is
-    /// not data available on the receiver, but it will not panic in the case
-    /// that the channel has been deallocated.
-    ///
-    /// In other words, this function has the same semantics as the `recv`
-    /// method except for the panic aspect.
-    ///
-    /// If the channel has hung up, then `Err` is returned. Otherwise `Ok` of
-    /// the value found on the receiver is returned.
-    #[unstable = "this function may be renamed to recv()"]
-    pub fn recv_opt(&self) -> Result<T, ()> {
-        loop {
-            let new_port = match *unsafe { self.inner() } {
-                Oneshot(ref p) => {
-                    match unsafe { (*p.get()).recv() } {
-                        Ok(t) => return Ok(t),
-                        Err(oneshot::Empty) => return unreachable!(),
-                        Err(oneshot::Disconnected) => return Err(()),
-                        Err(oneshot::Upgraded(rx)) => rx,
-                    }
-                }
-                Stream(ref p) => {
-                    match unsafe { (*p.get()).recv() } {
-                        Ok(t) => return Ok(t),
-                        Err(stream::Empty) => return unreachable!(),
-                        Err(stream::Disconnected) => return Err(()),
-                        Err(stream::Upgraded(rx)) => rx,
-                    }
-                }
-                Shared(ref p) => {
-                    match unsafe { (*p.get()).recv() } {
-                        Ok(t) => return Ok(t),
-                        Err(shared::Empty) => return unreachable!(),
-                        Err(shared::Disconnected) => return Err(()),
-                    }
-                }
-                Sync(ref p) => return unsafe { (*p.get()).recv() }
-            };
-            unsafe {
-                mem::swap(self.inner_mut(), new_port.inner_mut());
-            }
-        }
-    }
-
-    /// Returns an iterator that will block waiting for messages, but never
-    /// `panic!`. It will return `None` when the channel has hung up.
-    #[unstable]
-    pub fn iter<'a>(&'a self) -> Messages<'a, T> {
-        Messages { rx: self }
-    }
-}
-
-impl<T: Send> select::Packet for Receiver<T> {
-    fn can_recv(&self) -> bool {
-        loop {
-            let new_port = match *unsafe { self.inner() } {
-                Oneshot(ref p) => {
-                    match unsafe { (*p.get()).can_recv() } {
-                        Ok(ret) => return ret,
-                        Err(upgrade) => upgrade,
-                    }
-                }
-                Stream(ref p) => {
-                    match unsafe { (*p.get()).can_recv() } {
-                        Ok(ret) => return ret,
-                        Err(upgrade) => upgrade,
-                    }
-                }
-                Shared(ref p) => {
-                    return unsafe { (*p.get()).can_recv() };
-                }
-                Sync(ref p) => {
-                    return unsafe { (*p.get()).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() } {
-                Oneshot(ref p) => {
-                    match unsafe { (*p.get()).start_selection(token) } {
-                        oneshot::SelSuccess => return Installed,
-                        oneshot::SelCanceled => return Abort,
-                        oneshot::SelUpgraded(t, rx) => (t, rx),
-                    }
-                }
-                Stream(ref p) => {
-                    match unsafe { (*p.get()).start_selection(token) } {
-                        stream::SelSuccess => return Installed,
-                        stream::SelCanceled => return Abort,
-                        stream::SelUpgraded(t, rx) => (t, rx),
-                    }
-                }
-                Shared(ref p) => {
-                    return unsafe { (*p.get()).start_selection(token) };
-                }
-                Sync(ref p) => {
-                    return unsafe { (*p.get()).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() } {
-                Oneshot(ref p) => unsafe { (*p.get()).abort_selection() },
-                Stream(ref p) => unsafe {
-                    (*p.get()).abort_selection(was_upgrade)
-                },
-                Shared(ref p) => return unsafe {
-                    (*p.get()).abort_selection(was_upgrade)
-                },
-                Sync(ref p) => return unsafe {
-                    (*p.get()).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());
-            }
-        }
-    }
-}
-
-#[unstable]
-impl<'a, T: Send> Iterator<T> for Messages<'a, T> {
-    fn next(&mut self) -> Option<T> { self.rx.recv_opt().ok() }
-}
-
-#[unsafe_destructor]
-impl<T: Send> Drop for Receiver<T> {
-    fn drop(&mut self) {
-        match *unsafe { self.inner_mut() } {
-            Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); },
-            Stream(ref mut p) => unsafe { (*p.get()).drop_port(); },
-            Shared(ref mut p) => unsafe { (*p.get()).drop_port(); },
-            Sync(ref mut p) => unsafe { (*p.get()).drop_port(); },
-        }
-    }
-}
-
-/// A version of `UnsafeCell` intended for use in concurrent data
-/// structures (for example, you might put it in an `Arc`).
-struct RacyCell<T>(pub UnsafeCell<T>);
-
-impl<T> RacyCell<T> {
-
-    fn new(value: T) -> RacyCell<T> {
-        RacyCell(UnsafeCell { value: value })
-    }
-
-    unsafe fn get(&self) -> *mut T {
-        self.0.get()
-    }
-
-}
-
-unsafe impl<T:Send> Send for RacyCell<T> { }
-
-unsafe impl<T> kinds::Sync for RacyCell<T> { } // Oh dear
-
-
-#[cfg(test)]
-mod test {
-    use prelude::v1::*;
-
-    use os;
-    use super::*;
-    use thread::Thread;
-    use str::from_str;
-
-    pub fn stress_factor() -> uint {
-        match os::getenv("RUST_TEST_STRESS") {
-            Some(val) => from_str::<uint>(val.as_slice()).unwrap(),
-            None => 1,
-        }
-    }
-
-    #[test]
-    fn smoke() {
-        let (tx, rx) = channel::<int>();
-        tx.send(1);
-        assert_eq!(rx.recv(), 1);
-    }
-
-    #[test]
-    fn drop_full() {
-        let (tx, _rx) = channel();
-        tx.send(box 1i);
-    }
-
-    #[test]
-    fn drop_full_shared() {
-        let (tx, _rx) = channel();
-        drop(tx.clone());
-        drop(tx.clone());
-        tx.send(box 1i);
-    }
-
-    #[test]
-    fn smoke_shared() {
-        let (tx, rx) = channel::<int>();
-        tx.send(1);
-        assert_eq!(rx.recv(), 1);
-        let tx = tx.clone();
-        tx.send(1);
-        assert_eq!(rx.recv(), 1);
-    }
-
-    #[test]
-    fn smoke_threads() {
-        let (tx, rx) = channel::<int>();
-        let _t = Thread::spawn(move|| {
-            tx.send(1);
-        });
-        assert_eq!(rx.recv(), 1);
-    }
-
-    #[test]
-    #[should_fail]
-    fn smoke_port_gone() {
-        let (tx, rx) = channel::<int>();
-        drop(rx);
-        tx.send(1);
-    }
-
-    #[test]
-    #[should_fail]
-    fn smoke_shared_port_gone() {
-        let (tx, rx) = channel::<int>();
-        drop(rx);
-        tx.send(1);
-    }
-
-    #[test]
-    #[should_fail]
-    fn smoke_shared_port_gone2() {
-        let (tx, rx) = channel::<int>();
-        drop(rx);
-        let tx2 = tx.clone();
-        drop(tx);
-        tx2.send(1);
-    }
-
-    #[test]
-    #[should_fail]
-    fn port_gone_concurrent() {
-        let (tx, rx) = channel::<int>();
-        Thread::spawn(move|| {
-            rx.recv();
-        }).detach();
-        loop { tx.send(1) }
-    }
-
-    #[test]
-    #[should_fail]
-    fn port_gone_concurrent_shared() {
-        let (tx, rx) = channel::<int>();
-        let tx2 = tx.clone();
-        Thread::spawn(move|| {
-            rx.recv();
-        }).detach();
-        loop {
-            tx.send(1);
-            tx2.send(1);
-        }
-    }
-
-    #[test]
-    #[should_fail]
-    fn smoke_chan_gone() {
-        let (tx, rx) = channel::<int>();
-        drop(tx);
-        rx.recv();
-    }
-
-    #[test]
-    #[should_fail]
-    fn smoke_chan_gone_shared() {
-        let (tx, rx) = channel::<()>();
-        let tx2 = tx.clone();
-        drop(tx);
-        drop(tx2);
-        rx.recv();
-    }
-
-    #[test]
-    #[should_fail]
-    fn chan_gone_concurrent() {
-        let (tx, rx) = channel::<int>();
-        Thread::spawn(move|| {
-            tx.send(1);
-            tx.send(1);
-        }).detach();
-        loop { rx.recv(); }
-    }
-
-    #[test]
-    fn stress() {
-        let (tx, rx) = channel::<int>();
-        let t = Thread::spawn(move|| {
-            for _ in range(0u, 10000) { tx.send(1i); }
-        });
-        for _ in range(0u, 10000) {
-            assert_eq!(rx.recv(), 1);
-        }
-        t.join().ok().unwrap();
-    }
-
-    #[test]
-    fn stress_shared() {
-        static AMT: uint = 10000;
-        static NTHREADS: uint = 8;
-        let (tx, rx) = channel::<int>();
-
-        let t = Thread::spawn(move|| {
-            for _ in range(0, AMT * NTHREADS) {
-                assert_eq!(rx.recv(), 1);
-            }
-            match rx.try_recv() {
-                Ok(..) => panic!(),
-                _ => {}
-            }
-        });
-
-        for _ in range(0, NTHREADS) {
-            let tx = tx.clone();
-            Thread::spawn(move|| {
-                for _ in range(0, AMT) { tx.send(1); }
-            }).detach();
-        }
-        drop(tx);
-        t.join().ok().unwrap();
-    }
-
-    #[test]
-    fn send_from_outside_runtime() {
-        let (tx1, rx1) = channel::<()>();
-        let (tx2, rx2) = channel::<int>();
-        let t1 = Thread::spawn(move|| {
-            tx1.send(());
-            for _ in range(0i, 40) {
-                assert_eq!(rx2.recv(), 1);
-            }
-        });
-        rx1.recv();
-        let t2 = Thread::spawn(move|| {
-            for _ in range(0i, 40) {
-                tx2.send(1);
-            }
-        });
-        t1.join().ok().unwrap();
-        t2.join().ok().unwrap();
-    }
-
-    #[test]
-    fn recv_from_outside_runtime() {
-        let (tx, rx) = channel::<int>();
-        let t = Thread::spawn(move|| {
-            for _ in range(0i, 40) {
-                assert_eq!(rx.recv(), 1);
-            }
-        });
-        for _ in range(0u, 40) {
-            tx.send(1);
-        }
-        t.join().ok().unwrap();
-    }
-
-    #[test]
-    fn no_runtime() {
-        let (tx1, rx1) = channel::<int>();
-        let (tx2, rx2) = channel::<int>();
-        let t1 = Thread::spawn(move|| {
-            assert_eq!(rx1.recv(), 1);
-            tx2.send(2);
-        });
-        let t2 = Thread::spawn(move|| {
-            tx1.send(1);
-            assert_eq!(rx2.recv(), 2);
-        });
-        t1.join().ok().unwrap();
-        t2.join().ok().unwrap();
-    }
-
-    #[test]
-    fn oneshot_single_thread_close_port_first() {
-        // Simple test of closing without sending
-        let (_tx, rx) = channel::<int>();
-        drop(rx);
-    }
-
-    #[test]
-    fn oneshot_single_thread_close_chan_first() {
-        // Simple test of closing without sending
-        let (tx, _rx) = channel::<int>();
-        drop(tx);
-    }
-
-    #[test]
-    #[should_fail]
-    fn oneshot_single_thread_send_port_close() {
-        // Testing that the sender cleans up the payload if receiver is closed
-        let (tx, rx) = channel::<Box<int>>();
-        drop(rx);
-        tx.send(box 0);
-    }
-
-    #[test]
-    fn oneshot_single_thread_recv_chan_close() {
-        // Receiving on a closed chan will panic
-        let res = Thread::spawn(move|| {
-            let (tx, rx) = channel::<int>();
-            drop(tx);
-            rx.recv();
-        }).join();
-        // What is our res?
-        assert!(res.is_err());
-    }
-
-    #[test]
-    fn oneshot_single_thread_send_then_recv() {
-        let (tx, rx) = channel::<Box<int>>();
-        tx.send(box 10);
-        assert!(rx.recv() == box 10);
-    }
-
-    #[test]
-    fn oneshot_single_thread_try_send_open() {
-        let (tx, rx) = channel::<int>();
-        assert!(tx.send_opt(10).is_ok());
-        assert!(rx.recv() == 10);
-    }
-
-    #[test]
-    fn oneshot_single_thread_try_send_closed() {
-        let (tx, rx) = channel::<int>();
-        drop(rx);
-        assert!(tx.send_opt(10).is_err());
-    }
-
-    #[test]
-    fn oneshot_single_thread_try_recv_open() {
-        let (tx, rx) = channel::<int>();
-        tx.send(10);
-        assert!(rx.recv_opt() == Ok(10));
-    }
-
-    #[test]
-    fn oneshot_single_thread_try_recv_closed() {
-        let (tx, rx) = channel::<int>();
-        drop(tx);
-        assert!(rx.recv_opt() == Err(()));
-    }
-
-    #[test]
-    fn oneshot_single_thread_peek_data() {
-        let (tx, rx) = channel::<int>();
-        assert_eq!(rx.try_recv(), Err(Empty));
-        tx.send(10);
-        assert_eq!(rx.try_recv(), Ok(10));
-    }
-
-    #[test]
-    fn oneshot_single_thread_peek_close() {
-        let (tx, rx) = channel::<int>();
-        drop(tx);
-        assert_eq!(rx.try_recv(), Err(Disconnected));
-        assert_eq!(rx.try_recv(), Err(Disconnected));
-    }
-
-    #[test]
-    fn oneshot_single_thread_peek_open() {
-        let (_tx, rx) = channel::<int>();
-        assert_eq!(rx.try_recv(), Err(Empty));
-    }
-
-    #[test]
-    fn oneshot_multi_task_recv_then_send() {
-        let (tx, rx) = channel::<Box<int>>();
-        let _t = Thread::spawn(move|| {
-            assert!(rx.recv() == box 10);
-        });
-
-        tx.send(box 10);
-    }
-
-    #[test]
-    fn oneshot_multi_task_recv_then_close() {
-        let (tx, rx) = channel::<Box<int>>();
-        let _t = Thread::spawn(move|| {
-            drop(tx);
-        });
-        let res = Thread::spawn(move|| {
-            assert!(rx.recv() == box 10);
-        }).join();
-        assert!(res.is_err());
-    }
-
-    #[test]
-    fn oneshot_multi_thread_close_stress() {
-        for _ in range(0, stress_factor()) {
-            let (tx, rx) = channel::<int>();
-            let _t = Thread::spawn(move|| {
-                drop(rx);
-            });
-            drop(tx);
-        }
-    }
-
-    #[test]
-    fn oneshot_multi_thread_send_close_stress() {
-        for _ in range(0, stress_factor()) {
-            let (tx, rx) = channel::<int>();
-            let _t = Thread::spawn(move|| {
-                drop(rx);
-            });
-            let _ = Thread::spawn(move|| {
-                tx.send(1);
-            }).join();
-        }
-    }
-
-    #[test]
-    fn oneshot_multi_thread_recv_close_stress() {
-        for _ in range(0, stress_factor()) {
-            let (tx, rx) = channel::<int>();
-            Thread::spawn(move|| {
-                let res = Thread::spawn(move|| {
-                    rx.recv();
-                }).join();
-                assert!(res.is_err());
-            }).detach();
-            let _t = Thread::spawn(move|| {
-                Thread::spawn(move|| {
-                    drop(tx);
-                }).detach();
-            });
-        }
-    }
-
-    #[test]
-    fn oneshot_multi_thread_send_recv_stress() {
-        for _ in range(0, stress_factor()) {
-            let (tx, rx) = channel();
-            let _t = Thread::spawn(move|| {
-                tx.send(box 10i);
-            });
-            assert!(rx.recv() == box 10i);
-        }
-    }
-
-    #[test]
-    fn stream_send_recv_stress() {
-        for _ in range(0, stress_factor()) {
-            let (tx, rx) = channel();
-
-            send(tx, 0);
-            recv(rx, 0);
-
-            fn send(tx: Sender<Box<int>>, i: int) {
-                if i == 10 { return }
-
-                Thread::spawn(move|| {
-                    tx.send(box i);
-                    send(tx, i + 1);
-                }).detach();
-            }
-
-            fn recv(rx: Receiver<Box<int>>, i: int) {
-                if i == 10 { return }
-
-                Thread::spawn(move|| {
-                    assert!(rx.recv() == box i);
-                    recv(rx, i + 1);
-                }).detach();
-            }
-        }
-    }
-
-    #[test]
-    fn recv_a_lot() {
-        // Regression test that we don't run out of stack in scheduler context
-        let (tx, rx) = channel();
-        for _ in range(0i, 10000) { tx.send(()); }
-        for _ in range(0i, 10000) { rx.recv(); }
-    }
-
-    #[test]
-    fn shared_chan_stress() {
-        let (tx, rx) = channel();
-        let total = stress_factor() + 100;
-        for _ in range(0, total) {
-            let tx = tx.clone();
-            Thread::spawn(move|| {
-                tx.send(());
-            }).detach();
-        }
-
-        for _ in range(0, total) {
-            rx.recv();
-        }
-    }
-
-    #[test]
-    fn test_nested_recv_iter() {
-        let (tx, rx) = channel::<int>();
-        let (total_tx, total_rx) = channel::<int>();
-
-        let _t = Thread::spawn(move|| {
-            let mut acc = 0;
-            for x in rx.iter() {
-                acc += x;
-            }
-            total_tx.send(acc);
-        });
-
-        tx.send(3);
-        tx.send(1);
-        tx.send(2);
-        drop(tx);
-        assert_eq!(total_rx.recv(), 6);
-    }
-
-    #[test]
-    fn test_recv_iter_break() {
-        let (tx, rx) = channel::<int>();
-        let (count_tx, count_rx) = channel();
-
-        let _t = Thread::spawn(move|| {
-            let mut count = 0;
-            for x in rx.iter() {
-                if count >= 3 {
-                    break;
-                } else {
-                    count += x;
-                }
-            }
-            count_tx.send(count);
-        });
-
-        tx.send(2);
-        tx.send(2);
-        tx.send(2);
-        let _ = tx.send_opt(2);
-        drop(tx);
-        assert_eq!(count_rx.recv(), 4);
-    }
-
-    #[test]
-    fn try_recv_states() {
-        let (tx1, rx1) = channel::<int>();
-        let (tx2, rx2) = channel::<()>();
-        let (tx3, rx3) = channel::<()>();
-        let _t = Thread::spawn(move|| {
-            rx2.recv();
-            tx1.send(1);
-            tx3.send(());
-            rx2.recv();
-            drop(tx1);
-            tx3.send(());
-        });
-
-        assert_eq!(rx1.try_recv(), Err(Empty));
-        tx2.send(());
-        rx3.recv();
-        assert_eq!(rx1.try_recv(), Ok(1));
-        assert_eq!(rx1.try_recv(), Err(Empty));
-        tx2.send(());
-        rx3.recv();
-        assert_eq!(rx1.try_recv(), Err(Disconnected));
-    }
-
-    // This bug used to end up in a livelock inside of the Receiver destructor
-    // because the internal state of the Shared packet was corrupted
-    #[test]
-    fn destroy_upgraded_shared_port_when_sender_still_active() {
-        let (tx, rx) = channel();
-        let (tx2, rx2) = channel();
-        let _t = Thread::spawn(move|| {
-            rx.recv(); // wait on a oneshot
-            drop(rx);  // destroy a shared
-            tx2.send(());
-        });
-        // make sure the other task has gone to sleep
-        for _ in range(0u, 5000) { Thread::yield_now(); }
-
-        // upgrade to a shared chan and send a message
-        let t = tx.clone();
-        drop(tx);
-        t.send(());
-
-        // wait for the child task to exit before we exit
-        rx2.recv();
-    }
-}
-
-#[cfg(test)]
-mod sync_tests {
-    use prelude::v1::*;
-    use os;
-    use thread::Thread;
-    use super::*;
-    use str::from_str;
-
-    pub fn stress_factor() -> uint {
-        match os::getenv("RUST_TEST_STRESS") {
-            Some(val) => from_str::<uint>(val.as_slice()).unwrap(),
-            None => 1,
-        }
-    }
-
-    #[test]
-    fn smoke() {
-        let (tx, rx) = sync_channel::<int>(1);
-        tx.send(1);
-        assert_eq!(rx.recv(), 1);
-    }
-
-    #[test]
-    fn drop_full() {
-        let (tx, _rx) = sync_channel(1);
-        tx.send(box 1i);
-    }
-
-    #[test]
-    fn smoke_shared() {
-        let (tx, rx) = sync_channel::<int>(1);
-        tx.send(1);
-        assert_eq!(rx.recv(), 1);
-        let tx = tx.clone();
-        tx.send(1);
-        assert_eq!(rx.recv(), 1);
-    }
-
-    #[test]
-    fn smoke_threads() {
-        let (tx, rx) = sync_channel::<int>(0);
-        let _t = Thread::spawn(move|| {
-            tx.send(1);
-        });
-        assert_eq!(rx.recv(), 1);
-    }
-
-    #[test]
-    #[should_fail]
-    fn smoke_port_gone() {
-        let (tx, rx) = sync_channel::<int>(0);
-        drop(rx);
-        tx.send(1);
-    }
-
-    #[test]
-    #[should_fail]
-    fn smoke_shared_port_gone2() {
-        let (tx, rx) = sync_channel::<int>(0);
-        drop(rx);
-        let tx2 = tx.clone();
-        drop(tx);
-        tx2.send(1);
-    }
-
-    #[test]
-    #[should_fail]
-    fn port_gone_concurrent() {
-        let (tx, rx) = sync_channel::<int>(0);
-        Thread::spawn(move|| {
-            rx.recv();
-        }).detach();
-        loop { tx.send(1) }
-    }
-
-    #[test]
-    #[should_fail]
-    fn port_gone_concurrent_shared() {
-        let (tx, rx) = sync_channel::<int>(0);
-        let tx2 = tx.clone();
-        Thread::spawn(move|| {
-            rx.recv();
-        }).detach();
-        loop {
-            tx.send(1);
-            tx2.send(1);
-        }
-    }
-
-    #[test]
-    #[should_fail]
-    fn smoke_chan_gone() {
-        let (tx, rx) = sync_channel::<int>(0);
-        drop(tx);
-        rx.recv();
-    }
-
-    #[test]
-    #[should_fail]
-    fn smoke_chan_gone_shared() {
-        let (tx, rx) = sync_channel::<()>(0);
-        let tx2 = tx.clone();
-        drop(tx);
-        drop(tx2);
-        rx.recv();
-    }
-
-    #[test]
-    #[should_fail]
-    fn chan_gone_concurrent() {
-        let (tx, rx) = sync_channel::<int>(0);
-        Thread::spawn(move|| {
-            tx.send(1);
-            tx.send(1);
-        }).detach();
-        loop { rx.recv(); }
-    }
-
-    #[test]
-    fn stress() {
-        let (tx, rx) = sync_channel::<int>(0);
-        Thread::spawn(move|| {
-            for _ in range(0u, 10000) { tx.send(1); }
-        }).detach();
-        for _ in range(0u, 10000) {
-            assert_eq!(rx.recv(), 1);
-        }
-    }
-
-    #[test]
-    fn stress_shared() {
-        static AMT: uint = 1000;
-        static NTHREADS: uint = 8;
-        let (tx, rx) = sync_channel::<int>(0);
-        let (dtx, drx) = sync_channel::<()>(0);
-
-        Thread::spawn(move|| {
-            for _ in range(0, AMT * NTHREADS) {
-                assert_eq!(rx.recv(), 1);
-            }
-            match rx.try_recv() {
-                Ok(..) => panic!(),
-                _ => {}
-            }
-            dtx.send(());
-        }).detach();
-
-        for _ in range(0, NTHREADS) {
-            let tx = tx.clone();
-            Thread::spawn(move|| {
-                for _ in range(0, AMT) { tx.send(1); }
-            }).detach();
-        }
-        drop(tx);
-        drx.recv();
-    }
-
-    #[test]
-    fn oneshot_single_thread_close_port_first() {
-        // Simple test of closing without sending
-        let (_tx, rx) = sync_channel::<int>(0);
-        drop(rx);
-    }
-
-    #[test]
-    fn oneshot_single_thread_close_chan_first() {
-        // Simple test of closing without sending
-        let (tx, _rx) = sync_channel::<int>(0);
-        drop(tx);
-    }
-
-    #[test]
-    #[should_fail]
-    fn oneshot_single_thread_send_port_close() {
-        // Testing that the sender cleans up the payload if receiver is closed
-        let (tx, rx) = sync_channel::<Box<int>>(0);
-        drop(rx);
-        tx.send(box 0);
-    }
-
-    #[test]
-    fn oneshot_single_thread_recv_chan_close() {
-        // Receiving on a closed chan will panic
-        let res = Thread::spawn(move|| {
-            let (tx, rx) = sync_channel::<int>(0);
-            drop(tx);
-            rx.recv();
-        }).join();
-        // What is our res?
-        assert!(res.is_err());
-    }
-
-    #[test]
-    fn oneshot_single_thread_send_then_recv() {
-        let (tx, rx) = sync_channel::<Box<int>>(1);
-        tx.send(box 10);
-        assert!(rx.recv() == box 10);
-    }
-
-    #[test]
-    fn oneshot_single_thread_try_send_open() {
-        let (tx, rx) = sync_channel::<int>(1);
-        assert_eq!(tx.try_send(10), Ok(()));
-        assert!(rx.recv() == 10);
-    }
-
-    #[test]
-    fn oneshot_single_thread_try_send_closed() {
-        let (tx, rx) = sync_channel::<int>(0);
-        drop(rx);
-        assert_eq!(tx.try_send(10), Err(RecvDisconnected(10)));
-    }
-
-    #[test]
-    fn oneshot_single_thread_try_send_closed2() {
-        let (tx, _rx) = sync_channel::<int>(0);
-        assert_eq!(tx.try_send(10), Err(Full(10)));
-    }
-
-    #[test]
-    fn oneshot_single_thread_try_recv_open() {
-        let (tx, rx) = sync_channel::<int>(1);
-        tx.send(10);
-        assert!(rx.recv_opt() == Ok(10));
-    }
-
-    #[test]
-    fn oneshot_single_thread_try_recv_closed() {
-        let (tx, rx) = sync_channel::<int>(0);
-        drop(tx);
-        assert!(rx.recv_opt() == Err(()));
-    }
-
-    #[test]
-    fn oneshot_single_thread_peek_data() {
-        let (tx, rx) = sync_channel::<int>(1);
-        assert_eq!(rx.try_recv(), Err(Empty));
-        tx.send(10);
-        assert_eq!(rx.try_recv(), Ok(10));
-    }
-
-    #[test]
-    fn oneshot_single_thread_peek_close() {
-        let (tx, rx) = sync_channel::<int>(0);
-        drop(tx);
-        assert_eq!(rx.try_recv(), Err(Disconnected));
-        assert_eq!(rx.try_recv(), Err(Disconnected));
-    }
-
-    #[test]
-    fn oneshot_single_thread_peek_open() {
-        let (_tx, rx) = sync_channel::<int>(0);
-        assert_eq!(rx.try_recv(), Err(Empty));
-    }
-
-    #[test]
-    fn oneshot_multi_task_recv_then_send() {
-        let (tx, rx) = sync_channel::<Box<int>>(0);
-        let _t = Thread::spawn(move|| {
-            assert!(rx.recv() == box 10);
-        });
-
-        tx.send(box 10);
-    }
-
-    #[test]
-    fn oneshot_multi_task_recv_then_close() {
-        let (tx, rx) = sync_channel::<Box<int>>(0);
-        let _t = Thread::spawn(move|| {
-            drop(tx);
-        });
-        let res = Thread::spawn(move|| {
-            assert!(rx.recv() == box 10);
-        }).join();
-        assert!(res.is_err());
-    }
-
-    #[test]
-    fn oneshot_multi_thread_close_stress() {
-        for _ in range(0, stress_factor()) {
-            let (tx, rx) = sync_channel::<int>(0);
-            let _t = Thread::spawn(move|| {
-                drop(rx);
-            });
-            drop(tx);
-        }
-    }
-
-    #[test]
-    fn oneshot_multi_thread_send_close_stress() {
-        for _ in range(0, stress_factor()) {
-            let (tx, rx) = sync_channel::<int>(0);
-            let _t = Thread::spawn(move|| {
-                drop(rx);
-            });
-            let _ = Thread::spawn(move || {
-                tx.send(1);
-            }).join();
-        }
-    }
-
-    #[test]
-    fn oneshot_multi_thread_recv_close_stress() {
-        for _ in range(0, stress_factor()) {
-            let (tx, rx) = sync_channel::<int>(0);
-            let _t = Thread::spawn(move|| {
-                let res = Thread::spawn(move|| {
-                    rx.recv();
-                }).join();
-                assert!(res.is_err());
-            });
-            let _t = Thread::spawn(move|| {
-                Thread::spawn(move|| {
-                    drop(tx);
-                }).detach();
-            });
-        }
-    }
-
-    #[test]
-    fn oneshot_multi_thread_send_recv_stress() {
-        for _ in range(0, stress_factor()) {
-            let (tx, rx) = sync_channel::<Box<int>>(0);
-            let _t = Thread::spawn(move|| {
-                tx.send(box 10i);
-            });
-            assert!(rx.recv() == box 10i);
-        }
-    }
-
-    #[test]
-    fn stream_send_recv_stress() {
-        for _ in range(0, stress_factor()) {
-            let (tx, rx) = sync_channel::<Box<int>>(0);
-
-            send(tx, 0);
-            recv(rx, 0);
-
-            fn send(tx: SyncSender<Box<int>>, i: int) {
-                if i == 10 { return }
-
-                Thread::spawn(move|| {
-                    tx.send(box i);
-                    send(tx, i + 1);
-                }).detach();
-            }
-
-            fn recv(rx: Receiver<Box<int>>, i: int) {
-                if i == 10 { return }
-
-                Thread::spawn(move|| {
-                    assert!(rx.recv() == box i);
-                    recv(rx, i + 1);
-                }).detach();
-            }
-        }
-    }
-
-    #[test]
-    fn recv_a_lot() {
-        // Regression test that we don't run out of stack in scheduler context
-        let (tx, rx) = sync_channel(10000);
-        for _ in range(0u, 10000) { tx.send(()); }
-        for _ in range(0u, 10000) { rx.recv(); }
-    }
-
-    #[test]
-    fn shared_chan_stress() {
-        let (tx, rx) = sync_channel(0);
-        let total = stress_factor() + 100;
-        for _ in range(0, total) {
-            let tx = tx.clone();
-            Thread::spawn(move|| {
-                tx.send(());
-            }).detach();
-        }
-
-        for _ in range(0, total) {
-            rx.recv();
-        }
-    }
-
-    #[test]
-    fn test_nested_recv_iter() {
-        let (tx, rx) = sync_channel::<int>(0);
-        let (total_tx, total_rx) = sync_channel::<int>(0);
-
-        let _t = Thread::spawn(move|| {
-            let mut acc = 0;
-            for x in rx.iter() {
-                acc += x;
-            }
-            total_tx.send(acc);
-        });
-
-        tx.send(3);
-        tx.send(1);
-        tx.send(2);
-        drop(tx);
-        assert_eq!(total_rx.recv(), 6);
-    }
-
-    #[test]
-    fn test_recv_iter_break() {
-        let (tx, rx) = sync_channel::<int>(0);
-        let (count_tx, count_rx) = sync_channel(0);
-
-        let _t = Thread::spawn(move|| {
-            let mut count = 0;
-            for x in rx.iter() {
-                if count >= 3 {
-                    break;
-                } else {
-                    count += x;
-                }
-            }
-            count_tx.send(count);
-        });
-
-        tx.send(2);
-        tx.send(2);
-        tx.send(2);
-        let _ = tx.try_send(2);
-        drop(tx);
-        assert_eq!(count_rx.recv(), 4);
-    }
-
-    #[test]
-    fn try_recv_states() {
-        let (tx1, rx1) = sync_channel::<int>(1);
-        let (tx2, rx2) = sync_channel::<()>(1);
-        let (tx3, rx3) = sync_channel::<()>(1);
-        let _t = Thread::spawn(move|| {
-            rx2.recv();
-            tx1.send(1);
-            tx3.send(());
-            rx2.recv();
-            drop(tx1);
-            tx3.send(());
-        });
-
-        assert_eq!(rx1.try_recv(), Err(Empty));
-        tx2.send(());
-        rx3.recv();
-        assert_eq!(rx1.try_recv(), Ok(1));
-        assert_eq!(rx1.try_recv(), Err(Empty));
-        tx2.send(());
-        rx3.recv();
-        assert_eq!(rx1.try_recv(), Err(Disconnected));
-    }
-
-    // This bug used to end up in a livelock inside of the Receiver destructor
-    // because the internal state of the Shared packet was corrupted
-    #[test]
-    fn destroy_upgraded_shared_port_when_sender_still_active() {
-        let (tx, rx) = sync_channel::<()>(0);
-        let (tx2, rx2) = sync_channel::<()>(0);
-        let _t = Thread::spawn(move|| {
-            rx.recv(); // wait on a oneshot
-            drop(rx);  // destroy a shared
-            tx2.send(());
-        });
-        // make sure the other task has gone to sleep
-        for _ in range(0u, 5000) { Thread::yield_now(); }
-
-        // upgrade to a shared chan and send a message
-        let t = tx.clone();
-        drop(tx);
-        t.send(());
-
-        // wait for the child task to exit before we exit
-        rx2.recv();
-    }
-
-    #[test]
-    fn send_opt1() {
-        let (tx, rx) = sync_channel::<int>(0);
-        let _t = Thread::spawn(move|| { rx.recv(); });
-        assert_eq!(tx.send_opt(1), Ok(()));
-    }
-
-    #[test]
-    fn send_opt2() {
-        let (tx, rx) = sync_channel::<int>(0);
-        let _t = Thread::spawn(move|| { drop(rx); });
-        assert_eq!(tx.send_opt(1), Err(1));
-    }
-
-    #[test]
-    fn send_opt3() {
-        let (tx, rx) = sync_channel::<int>(1);
-        assert_eq!(tx.send_opt(1), Ok(()));
-        let _t = Thread::spawn(move|| { drop(rx); });
-        assert_eq!(tx.send_opt(1), Err(1));
-    }
-
-    #[test]
-    fn send_opt4() {
-        let (tx, rx) = sync_channel::<int>(0);
-        let tx2 = tx.clone();
-        let (done, donerx) = channel();
-        let done2 = done.clone();
-        let _t = Thread::spawn(move|| {
-            assert_eq!(tx.send_opt(1), Err(1));
-            done.send(());
-        });
-        let _t = Thread::spawn(move|| {
-            assert_eq!(tx2.send_opt(2), Err(2));
-            done2.send(());
-        });
-        drop(rx);
-        donerx.recv();
-        donerx.recv();
-    }
-
-    #[test]
-    fn try_send1() {
-        let (tx, _rx) = sync_channel::<int>(0);
-        assert_eq!(tx.try_send(1), Err(Full(1)));
-    }
-
-    #[test]
-    fn try_send2() {
-        let (tx, _rx) = sync_channel::<int>(1);
-        assert_eq!(tx.try_send(1), Ok(()));
-        assert_eq!(tx.try_send(1), Err(Full(1)));
-    }
-
-    #[test]
-    fn try_send3() {
-        let (tx, rx) = sync_channel::<int>(1);
-        assert_eq!(tx.try_send(1), Ok(()));
-        drop(rx);
-        assert_eq!(tx.try_send(1), Err(RecvDisconnected(1)));
-    }
-
-    #[test]
-    fn issue_15761() {
-        fn repro() {
-            let (tx1, rx1) = sync_channel::<()>(3);
-            let (tx2, rx2) = sync_channel::<()>(3);
-
-            let _t = Thread::spawn(move|| {
-                rx1.recv();
-                tx2.try_send(()).unwrap();
-            });
-
-            tx1.try_send(()).unwrap();
-            rx2.recv();
-        }
-
-        for _ in range(0u, 100) {
-            repro()
-        }
-    }
-}
diff --git a/src/libstd/comm/mpsc_queue.rs b/src/libstd/comm/mpsc_queue.rs
deleted file mode 100644 (file)
index d1b6d0d..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *    1. Redistributions of source code must retain the above copyright notice,
- *       this list of conditions and the following disclaimer.
- *
- *    2. Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are
- * those of the authors and should not be interpreted as representing official
- * policies, either expressed or implied, of Dmitry Vyukov.
- */
-
-//! A mostly lock-free multi-producer, single consumer queue.
-//!
-//! This module contains an implementation of a concurrent MPSC queue. This
-//! queue can be used to share data between tasks, and is also used as the
-//! building block of channels in rust.
-//!
-//! Note that the current implementation of this queue has a caveat of the `pop`
-//! method, and see the method for more information about it. Due to this
-//! caveat, this queue may not be appropriate for all use-cases.
-
-#![experimental]
-
-// http://www.1024cores.net/home/lock-free-algorithms
-//                         /queues/non-intrusive-mpsc-node-based-queue
-
-pub use self::PopResult::*;
-
-use core::prelude::*;
-
-use alloc::boxed::Box;
-use core::mem;
-use core::cell::UnsafeCell;
-
-use sync::atomic::{AtomicPtr, Release, Acquire, AcqRel, Relaxed};
-
-/// A result of the `pop` function.
-pub enum PopResult<T> {
-    /// Some data has been popped
-    Data(T),
-    /// The queue is empty
-    Empty,
-    /// The queue is in an inconsistent state. Popping data should succeed, but
-    /// some pushers have yet to make enough progress in order allow a pop to
-    /// succeed. It is recommended that a pop() occur "in the near future" in
-    /// order to see if the sender has made progress or not
-    Inconsistent,
-}
-
-struct Node<T> {
-    next: AtomicPtr<Node<T>>,
-    value: Option<T>,
-}
-
-/// The multi-producer single-consumer structure. This is not cloneable, but it
-/// may be safely shared so long as it is guaranteed that there is only one
-/// popper at a time (many pushers are allowed).
-pub struct Queue<T> {
-    head: AtomicPtr<Node<T>>,
-    tail: UnsafeCell<*mut Node<T>>,
-}
-
-unsafe impl<T:Send> Send for Queue<T> { }
-unsafe impl<T:Send> Sync for Queue<T> { }
-
-impl<T> Node<T> {
-    unsafe fn new(v: Option<T>) -> *mut Node<T> {
-        mem::transmute(box Node {
-            next: AtomicPtr::new(0 as *mut Node<T>),
-            value: v,
-        })
-    }
-}
-
-impl<T: Send> Queue<T> {
-    /// Creates a new queue that is safe to share among multiple producers and
-    /// one consumer.
-    pub fn new() -> Queue<T> {
-        let stub = unsafe { Node::new(None) };
-        Queue {
-            head: AtomicPtr::new(stub),
-            tail: UnsafeCell::new(stub),
-        }
-    }
-
-    /// Pushes a new value onto this queue.
-    pub fn push(&self, t: T) {
-        unsafe {
-            let n = Node::new(Some(t));
-            let prev = self.head.swap(n, AcqRel);
-            (*prev).next.store(n, Release);
-        }
-    }
-
-    /// Pops some data from this queue.
-    ///
-    /// Note that the current implementation means that this function cannot
-    /// return `Option<T>`. It is possible for this queue to be in an
-    /// inconsistent state where many pushes have succeeded and completely
-    /// finished, but pops cannot return `Some(t)`. This inconsistent state
-    /// happens when a pusher is pre-empted at an inopportune moment.
-    ///
-    /// This inconsistent state means that this queue does indeed have data, but
-    /// it does not currently have access to it at this time.
-    pub fn pop(&self) -> PopResult<T> {
-        unsafe {
-            let tail = *self.tail.get();
-            let next = (*tail).next.load(Acquire);
-
-            if !next.is_null() {
-                *self.tail.get() = next;
-                assert!((*tail).value.is_none());
-                assert!((*next).value.is_some());
-                let ret = (*next).value.take().unwrap();
-                let _: Box<Node<T>> = mem::transmute(tail);
-                return Data(ret);
-            }
-
-            if self.head.load(Acquire) == tail {Empty} else {Inconsistent}
-        }
-    }
-}
-
-#[unsafe_destructor]
-impl<T: Send> Drop for Queue<T> {
-    fn drop(&mut self) {
-        unsafe {
-            let mut cur = *self.tail.get();
-            while !cur.is_null() {
-                let next = (*cur).next.load(Relaxed);
-                let _: Box<Node<T>> = mem::transmute(cur);
-                cur = next;
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use prelude::v1::*;
-
-    use comm::channel;
-    use super::{Queue, Data, Empty, Inconsistent};
-    use sync::Arc;
-    use thread::Thread;
-
-    #[test]
-    fn test_full() {
-        let q = Queue::new();
-        q.push(box 1i);
-        q.push(box 2i);
-    }
-
-    #[test]
-    fn test() {
-        let nthreads = 8u;
-        let nmsgs = 1000u;
-        let q = Queue::new();
-        match q.pop() {
-            Empty => {}
-            Inconsistent | Data(..) => panic!()
-        }
-        let (tx, rx) = channel();
-        let q = Arc::new(q);
-
-        for _ in range(0, nthreads) {
-            let tx = tx.clone();
-            let q = q.clone();
-            Thread::spawn(move|| {
-                for i in range(0, nmsgs) {
-                    q.push(i);
-                }
-                tx.send(());
-            }).detach();
-        }
-
-        let mut i = 0u;
-        while i < nthreads * nmsgs {
-            match q.pop() {
-                Empty | Inconsistent => {},
-                Data(_) => { i += 1 }
-            }
-        }
-        drop(tx);
-        for _ in range(0, nthreads) {
-            rx.recv();
-        }
-    }
-}
diff --git a/src/libstd/comm/oneshot.rs b/src/libstd/comm/oneshot.rs
deleted file mode 100644 (file)
index 9c5a651..0000000
+++ /dev/null
@@ -1,375 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/// Oneshot channels/ports
-///
-/// This is the initial flavor of channels/ports used for comm module. This is
-/// an optimization for the one-use case of a channel. The major optimization of
-/// this type is to have one and exactly one allocation when the chan/port pair
-/// is created.
-///
-/// Another possible optimization would be to not use an Arc box because
-/// in theory we know when the shared packet can be deallocated (no real need
-/// for the atomic reference counting), but I was having trouble how to destroy
-/// the data early in a drop of a Port.
-///
-/// # Implementation
-///
-/// Oneshots are implemented around one atomic uint variable. This variable
-/// indicates both the state of the port/chan but also contains any tasks
-/// blocked on the port. All atomic operations happen on this one word.
-///
-/// In order to upgrade a oneshot channel, an upgrade is considered a disconnect
-/// on behalf of the channel side of things (it can be mentally thought of as
-/// consuming the port). This upgrade is then also stored in the shared packet.
-/// The one caveat to consider is that when a port sees a disconnected channel
-/// it must check for data because there is no "data plus upgrade" state.
-
-pub use self::Failure::*;
-pub use self::UpgradeResult::*;
-pub use self::SelectionResult::*;
-use self::MyUpgrade::*;
-
-use core::prelude::*;
-
-use comm::Receiver;
-use comm::blocking::{mod, SignalToken};
-use core::mem;
-use sync::atomic;
-
-// Various states you can find a port in.
-const EMPTY: uint = 0;          // initial state: no data, no blocked reciever
-const DATA: uint = 1;           // data ready for receiver to take
-const DISCONNECTED: uint = 2;   // channel is disconnected OR upgraded
-// Any other value represents a pointer to a SignalToken value. The
-// protocol ensures that when the state moves *to* a pointer,
-// ownership of the token is given to the packet, and when the state
-// moves *from* a pointer, ownership of the token is transferred to
-// whoever changed the state.
-
-pub struct Packet<T> {
-    // Internal state of the chan/port pair (stores the blocked task as well)
-    state: atomic::AtomicUint,
-    // One-shot data slot location
-    data: Option<T>,
-    // when used for the second time, a oneshot channel must be upgraded, and
-    // this contains the slot for the upgrade
-    upgrade: MyUpgrade<T>,
-}
-
-pub enum Failure<T> {
-    Empty,
-    Disconnected,
-    Upgraded(Receiver<T>),
-}
-
-pub enum UpgradeResult {
-    UpSuccess,
-    UpDisconnected,
-    UpWoke(SignalToken),
-}
-
-pub enum SelectionResult<T> {
-    SelCanceled,
-    SelUpgraded(SignalToken, Receiver<T>),
-    SelSuccess,
-}
-
-enum MyUpgrade<T> {
-    NothingSent,
-    SendUsed,
-    GoUp(Receiver<T>),
-}
-
-impl<T: Send> Packet<T> {
-    pub fn new() -> Packet<T> {
-        Packet {
-            data: None,
-            upgrade: NothingSent,
-            state: atomic::AtomicUint::new(EMPTY),
-        }
-    }
-
-    pub fn send(&mut self, t: T) -> Result<(), T> {
-        // Sanity check
-        match self.upgrade {
-            NothingSent => {}
-            _ => panic!("sending on a oneshot that's already sent on "),
-        }
-        assert!(self.data.is_none());
-        self.data = Some(t);
-        self.upgrade = SendUsed;
-
-        match self.state.swap(DATA, atomic::SeqCst) {
-            // Sent the data, no one was waiting
-            EMPTY => Ok(()),
-
-            // Couldn't send the data, the port hung up first. Return the data
-            // back up the stack.
-            DISCONNECTED => {
-                Err(self.data.take().unwrap())
-            }
-
-            // Not possible, these are one-use channels
-            DATA => unreachable!(),
-
-            // There is a thread waiting on the other end. We leave the 'DATA'
-            // state inside so it'll pick it up on the other end.
-            ptr => unsafe {
-                SignalToken::cast_from_uint(ptr).signal();
-                Ok(())
-            }
-        }
-    }
-
-    // Just tests whether this channel has been sent on or not, this is only
-    // safe to use from the sender.
-    pub fn sent(&self) -> bool {
-        match self.upgrade {
-            NothingSent => false,
-            _ => true,
-        }
-    }
-
-    pub fn recv(&mut self) -> Result<T, Failure<T>> {
-        // Attempt to not block the task (it's a little expensive). If it looks
-        // like we're not empty, then immediately go through to `try_recv`.
-        if self.state.load(atomic::SeqCst) == EMPTY {
-            let (wait_token, signal_token) = blocking::tokens();
-            let ptr = unsafe { signal_token.cast_to_uint() };
-
-            // race with senders to enter the blocking state
-            if self.state.compare_and_swap(EMPTY, ptr, atomic::SeqCst) == EMPTY {
-                wait_token.wait();
-                debug_assert!(self.state.load(atomic::SeqCst) != EMPTY);
-            } else {
-                // drop the signal token, since we never blocked
-                drop(unsafe { SignalToken::cast_from_uint(ptr) });
-            }
-        }
-
-        self.try_recv()
-    }
-
-    pub fn try_recv(&mut self) -> Result<T, Failure<T>> {
-        match self.state.load(atomic::SeqCst) {
-            EMPTY => Err(Empty),
-
-            // We saw some data on the channel, but the channel can be used
-            // again to send us an upgrade. As a result, we need to re-insert
-            // into the channel that there's no data available (otherwise we'll
-            // just see DATA next time). This is done as a cmpxchg because if
-            // the state changes under our feet we'd rather just see that state
-            // change.
-            DATA => {
-                self.state.compare_and_swap(DATA, EMPTY, atomic::SeqCst);
-                match self.data.take() {
-                    Some(data) => Ok(data),
-                    None => unreachable!(),
-                }
-            }
-
-            // There's no guarantee that we receive before an upgrade happens,
-            // and an upgrade flags the channel as disconnected, so when we see
-            // this we first need to check if there's data available and *then*
-            // we go through and process the upgrade.
-            DISCONNECTED => {
-                match self.data.take() {
-                    Some(data) => Ok(data),
-                    None => {
-                        match mem::replace(&mut self.upgrade, SendUsed) {
-                            SendUsed | NothingSent => Err(Disconnected),
-                            GoUp(upgrade) => Err(Upgraded(upgrade))
-                        }
-                    }
-                }
-            }
-
-            // We are the sole receiver; there cannot be a blocking
-            // receiver already.
-            _ => unreachable!()
-        }
-    }
-
-    // Returns whether the upgrade was completed. If the upgrade wasn't
-    // completed, then the port couldn't get sent to the other half (it will
-    // never receive it).
-    pub fn upgrade(&mut self, up: Receiver<T>) -> UpgradeResult {
-        let prev = match self.upgrade {
-            NothingSent => NothingSent,
-            SendUsed => SendUsed,
-            _ => panic!("upgrading again"),
-        };
-        self.upgrade = GoUp(up);
-
-        match self.state.swap(DISCONNECTED, atomic::SeqCst) {
-            // If the channel is empty or has data on it, then we're good to go.
-            // Senders will check the data before the upgrade (in case we
-            // plastered over the DATA state).
-            DATA | EMPTY => UpSuccess,
-
-            // If the other end is already disconnected, then we failed the
-            // upgrade. Be sure to trash the port we were given.
-            DISCONNECTED => { self.upgrade = prev; UpDisconnected }
-
-            // If someone's waiting, we gotta wake them up
-            ptr => UpWoke(unsafe { SignalToken::cast_from_uint(ptr) })
-        }
-    }
-
-    pub fn drop_chan(&mut self) {
-        match self.state.swap(DISCONNECTED, atomic::SeqCst) {
-            DATA | DISCONNECTED | EMPTY => {}
-
-            // If someone's waiting, we gotta wake them up
-            ptr => unsafe {
-                SignalToken::cast_from_uint(ptr).signal();
-            }
-        }
-    }
-
-    pub fn drop_port(&mut self) {
-        match self.state.swap(DISCONNECTED, atomic::SeqCst) {
-            // An empty channel has nothing to do, and a remotely disconnected
-            // channel also has nothing to do b/c we're about to run the drop
-            // glue
-            DISCONNECTED | EMPTY => {}
-
-            // There's data on the channel, so make sure we destroy it promptly.
-            // This is why not using an arc is a little difficult (need the box
-            // to stay valid while we take the data).
-            DATA => { self.data.take().unwrap(); }
-
-            // We're the only ones that can block on this port
-            _ => unreachable!()
-        }
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    // 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(&mut self) -> Result<bool, Receiver<T>> {
-        match self.state.load(atomic::SeqCst) {
-            EMPTY => Ok(false), // Welp, we tried
-            DATA => Ok(true),   // we have some un-acquired data
-            DISCONNECTED if self.data.is_some() => Ok(true), // we have data
-            DISCONNECTED => {
-                match mem::replace(&mut self.upgrade, 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 => { self.upgrade = 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(&mut self, token: SignalToken) -> SelectionResult<T> {
-        let ptr = unsafe { token.cast_to_uint() };
-        match self.state.compare_and_swap(EMPTY, ptr, atomic::SeqCst) {
-            EMPTY => SelSuccess,
-            DATA => {
-                drop(unsafe { SignalToken::cast_from_uint(ptr) });
-                SelCanceled
-            }
-            DISCONNECTED if self.data.is_some() => {
-                drop(unsafe { SignalToken::cast_from_uint(ptr) });
-                SelCanceled
-            }
-            DISCONNECTED => {
-                match mem::replace(&mut self.upgrade, SendUsed) {
-                    // The other end sent us an upgrade, so we need to
-                    // propagate upwards whether the upgrade can receive
-                    // data
-                    GoUp(upgrade) => {
-                        SelUpgraded(unsafe { SignalToken::cast_from_uint(ptr) }, upgrade)
-                    }
-
-                    // If the other end disconnected without sending an
-                    // upgrade, then we have data to receive (the channel is
-                    // disconnected).
-                    up => {
-                        self.upgrade = up;
-                        drop(unsafe { SignalToken::cast_from_uint(ptr) });
-                        SelCanceled
-                    }
-                }
-            }
-            _ => unreachable!(), // we're the "one blocker"
-        }
-    }
-
-    // Remove a previous selecting task from this port. This ensures that the
-    // blocked task will no longer be visible to any other threads.
-    //
-    // The return value indicates whether there's data on this port.
-    pub fn abort_selection(&mut self) -> Result<bool, Receiver<T>> {
-        let state = match self.state.load(atomic::SeqCst) {
-            // Each of these states means that no further activity will happen
-            // with regard to abortion selection
-            s @ EMPTY |
-            s @ DATA |
-            s @ DISCONNECTED => s,
-
-            // If we've got a blocked task, then use an atomic to gain ownership
-            // of it (may fail)
-            ptr => self.state.compare_and_swap(ptr, EMPTY, atomic::SeqCst)
-        };
-
-        // Now that we've got ownership of our state, figure out what to do
-        // about it.
-        match state {
-            EMPTY => unreachable!(),
-            // our task used for select was stolen
-            DATA => Ok(true),
-
-            // If the other end has hung up, then we have complete ownership
-            // of the port. First, check if there was data waiting for us. This
-            // is possible if the other end sent something and then hung up.
-            //
-            // We then need to check to see if there was an upgrade requested,
-            // and if so, the upgraded port needs to have its selection aborted.
-            DISCONNECTED => {
-                if self.data.is_some() {
-                    Ok(true)
-                } else {
-                    match mem::replace(&mut self.upgrade, SendUsed) {
-                        GoUp(port) => Err(port),
-                        _ => Ok(true),
-                    }
-                }
-            }
-
-            // We woke ourselves up from select.
-            ptr => unsafe {
-                drop(SignalToken::cast_from_uint(ptr));
-                Ok(false)
-            }
-        }
-    }
-}
-
-#[unsafe_destructor]
-impl<T: Send> Drop for Packet<T> {
-    fn drop(&mut self) {
-        assert_eq!(self.state.load(atomic::SeqCst), DISCONNECTED);
-    }
-}
diff --git a/src/libstd/comm/select.rs b/src/libstd/comm/select.rs
deleted file mode 100644 (file)
index 5c47677..0000000
+++ /dev/null
@@ -1,749 +0,0 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! 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.
-//!
-//! # Example
-//!
-//! ```rust
-//! use std::comm::channel;
-//!
-//! let (tx1, rx1) = channel();
-//! let (tx2, rx2) = channel();
-//!
-//! tx1.send(1i);
-//! tx2.send(2i);
-//!
-//! select! {
-//!     val = rx1.recv() => {
-//!         assert_eq!(val, 1i);
-//!     },
-//!     val = rx2.recv() => {
-//!         assert_eq!(val, 2i);
-//!     }
-//! }
-//! ```
-
-#![allow(dead_code)]
-#![experimental = "This implementation, while likely sufficient, is unsafe and \
-                   likely to be error prone. At some point in the future this \
-                   module will likely be replaced, and it is currently \
-                   unknown how much API breakage that will cause. The ability \
-                   to select over a number of channels will remain forever, \
-                   but no guarantees beyond this are being made"]
-
-
-use core::prelude::*;
-
-use core::cell::Cell;
-use core::kinds::marker;
-use core::mem;
-use core::uint;
-
-use comm::Receiver;
-use comm::blocking::{mod, 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 {
-    head: *mut Handle<'static, ()>,
-    tail: *mut Handle<'static, ()>,
-    next_id: Cell<uint>,
-    marker1: marker::NoSend,
-}
-
-/// 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:'rx> {
-    /// The ID of this handle, used to compare against the return value of
-    /// `Select::wait()`
-    id: uint,
-    selector: &'rx Select,
-    next: *mut Handle<'static, ()>,
-    prev: *mut Handle<'static, ()>,
-    added: bool,
-    packet: &'rx (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)]
-#[deriving(PartialEq)]
-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 and
-    /// `wait` will panic!() if called.
-    ///
-    /// Usage of this struct directly can sometimes be burdensome, and usage is
-    /// rather much easier through the `select!` macro.
-    pub fn new() -> Select {
-        Select {
-            marker1: marker::NoSend,
-            head: 0 as *mut Handle<'static, ()>,
-            tail: 0 as *mut Handle<'static, ()>,
-            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: id,
-            selector: self,
-            next: 0 as *mut Handle<'static, ()>,
-            prev: 0 as *mut Handle<'static, ()>,
-            added: false,
-            rx: 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) -> uint {
-        self.wait2(true)
-    }
-
-    /// Helper method for skipping the preflight checks during testing
-    fn wait2(&self, do_preflight_checks: bool) -> uint {
-        // 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 task. 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 = uint::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 != uint::MAX);
-            return ready_id;
-        }
-    }
-
-    fn iter(&self) -> Packets { Packets { cur: self.head } }
-}
-
-impl<'rx, T: Send> Handle<'rx, T> {
-    /// Retrieve the id of this handle.
-    #[inline]
-    pub fn id(&self) -> uint { self.id }
-
-    /// Receive a value on the underlying receiver. Has the same semantics as
-    /// `Receiver.recv`
-    pub fn recv(&mut self) -> T { self.rx.recv() }
-    /// Block 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_opt`
-    pub fn recv_opt(&mut self) -> Result<T, ()> { self.rx.recv_opt() }
-
-    /// 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 Select = mem::transmute(&*self.selector);
-        let me: *mut Handle<'static, ()> = mem::transmute(&*self);
-
-        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 Select = mem::transmute(&*self.selector);
-        let me: *mut Handle<'static, ()> = mem::transmute(&*self);
-
-        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 = 0 as *mut Handle<'static, ()>;
-        self.prev = 0 as *mut Handle<'static, ()>;
-
-        self.added = false;
-    }
-}
-
-#[unsafe_destructor]
-impl Drop for Select {
-    fn drop(&mut self) {
-        assert!(self.head.is_null());
-        assert!(self.tail.is_null());
-    }
-}
-
-#[unsafe_destructor]
-impl<'rx, T: Send> Drop for Handle<'rx, T> {
-    fn drop(&mut self) {
-        unsafe { self.remove() }
-    }
-}
-
-impl Iterator<*mut Handle<'static, ()>> for Packets {
-    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
-        }
-    }
-}
-
-#[cfg(test)]
-#[allow(unused_imports)]
-mod test {
-    use prelude::v1::*;
-
-    use super::*;
-    use comm::*;
-    use thread::Thread;
-
-    // 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),+
-        ) => ({
-            use comm::Select;
-            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::<int>();
-        let (tx2, rx2) = channel::<int>();
-        tx1.send(1);
-        select! {
-            foo = rx1.recv() => { assert_eq!(foo, 1); },
-            _bar = rx2.recv() => { panic!() }
-        }
-        tx2.send(2);
-        select! {
-            _foo = rx1.recv() => { panic!() },
-            bar = rx2.recv() => { assert_eq!(bar, 2) }
-        }
-        drop(tx1);
-        select! {
-            foo = rx1.recv_opt() => { assert_eq!(foo, Err(())); },
-            _bar = rx2.recv() => { panic!() }
-        }
-        drop(tx2);
-        select! {
-            bar = rx2.recv_opt() => { assert_eq!(bar, Err(())); }
-        }
-    }
-
-    #[test]
-    fn smoke2() {
-        let (_tx1, rx1) = channel::<int>();
-        let (_tx2, rx2) = channel::<int>();
-        let (_tx3, rx3) = channel::<int>();
-        let (_tx4, rx4) = channel::<int>();
-        let (tx5, rx5) = channel::<int>();
-        tx5.send(4);
-        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, 4); }
-        }
-    }
-
-    #[test]
-    fn closed() {
-        let (_tx1, rx1) = channel::<int>();
-        let (tx2, rx2) = channel::<int>();
-        drop(tx2);
-
-        select! {
-            _a1 = rx1.recv_opt() => { panic!() },
-            a2 = rx2.recv_opt() => { assert_eq!(a2, Err(())); }
-        }
-    }
-
-    #[test]
-    fn unblocks() {
-        let (tx1, rx1) = channel::<int>();
-        let (_tx2, rx2) = channel::<int>();
-        let (tx3, rx3) = channel::<int>();
-
-        let _t = Thread::spawn(move|| {
-            for _ in range(0u, 20) { Thread::yield_now(); }
-            tx1.send(1);
-            rx3.recv();
-            for _ in range(0u, 20) { Thread::yield_now(); }
-        });
-
-        select! {
-            a = rx1.recv() => { assert_eq!(a, 1); },
-            _b = rx2.recv() => { panic!() }
-        }
-        tx3.send(1);
-        select! {
-            a = rx1.recv_opt() => { assert_eq!(a, Err(())); },
-            _b = rx2.recv() => { panic!() }
-        }
-    }
-
-    #[test]
-    fn both_ready() {
-        let (tx1, rx1) = channel::<int>();
-        let (tx2, rx2) = channel::<int>();
-        let (tx3, rx3) = channel::<()>();
-
-        let _t = Thread::spawn(move|| {
-            for _ in range(0u, 20) { Thread::yield_now(); }
-            tx1.send(1);
-            tx2.send(2);
-            rx3.recv();
-        });
-
-        select! {
-            a = rx1.recv() => { assert_eq!(a, 1); },
-            a = rx2.recv() => { assert_eq!(a, 2); }
-        }
-        select! {
-            a = rx1.recv() => { assert_eq!(a, 1); },
-            a = rx2.recv() => { assert_eq!(a, 2); }
-        }
-        assert_eq!(rx1.try_recv(), Err(Empty));
-        assert_eq!(rx2.try_recv(), Err(Empty));
-        tx3.send(());
-    }
-
-    #[test]
-    fn stress() {
-        static AMT: int = 10000;
-        let (tx1, rx1) = channel::<int>();
-        let (tx2, rx2) = channel::<int>();
-        let (tx3, rx3) = channel::<()>();
-
-        let _t = Thread::spawn(move|| {
-            for i in range(0, AMT) {
-                if i % 2 == 0 {
-                    tx1.send(i);
-                } else {
-                    tx2.send(i);
-                }
-                rx3.recv();
-            }
-        });
-
-        for i in range(0, AMT) {
-            select! {
-                i1 = rx1.recv() => { assert!(i % 2 == 0 && i == i1); },
-                i2 = rx2.recv() => { assert!(i % 2 == 1 && i == i2); }
-            }
-            tx3.send(());
-        }
-    }
-
-    #[test]
-    fn cloning() {
-        let (tx1, rx1) = channel::<int>();
-        let (_tx2, rx2) = channel::<int>();
-        let (tx3, rx3) = channel::<()>();
-
-        let _t = Thread::spawn(move|| {
-            rx3.recv();
-            tx1.clone();
-            assert_eq!(rx3.try_recv(), Err(Empty));
-            tx1.send(2);
-            rx3.recv();
-        });
-
-        tx3.send(());
-        select! {
-            _i1 = rx1.recv() => {},
-            _i2 = rx2.recv() => panic!()
-        }
-        tx3.send(());
-    }
-
-    #[test]
-    fn cloning2() {
-        let (tx1, rx1) = channel::<int>();
-        let (_tx2, rx2) = channel::<int>();
-        let (tx3, rx3) = channel::<()>();
-
-        let _t = Thread::spawn(move|| {
-            rx3.recv();
-            tx1.clone();
-            assert_eq!(rx3.try_recv(), Err(Empty));
-            tx1.send(2);
-            rx3.recv();
-        });
-
-        tx3.send(());
-        select! {
-            _i1 = rx1.recv() => {},
-            _i2 = rx2.recv() => panic!()
-        }
-        tx3.send(());
-    }
-
-    #[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(());
-        });
-
-        for _ in range(0u, 1000) { Thread::yield_now(); }
-        drop(tx1.clone());
-        tx2.send(());
-        rx3.recv();
-    }
-
-    #[test]
-    fn preflight1() {
-        let (tx, rx) = channel();
-        tx.send(());
-        select! {
-            () = rx.recv() => {}
-        }
-    }
-
-    #[test]
-    fn preflight2() {
-        let (tx, rx) = channel();
-        tx.send(());
-        tx.send(());
-        select! {
-            () = rx.recv() => {}
-        }
-    }
-
-    #[test]
-    fn preflight3() {
-        let (tx, rx) = channel();
-        drop(tx.clone());
-        tx.send(());
-        select! {
-            () = rx.recv() => {}
-        }
-    }
-
-    #[test]
-    fn preflight4() {
-        let (tx, rx) = channel();
-        tx.send(());
-        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(());
-        tx.send(());
-        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(());
-        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(());
-        drop(tx);
-        rx.recv();
-        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(());
-        drop(tx);
-        rx.recv();
-        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! {
-                () = rx1.recv() => {}
-            }
-            tx2.send(());
-        });
-
-        for _ in range(0u, 100) { Thread::yield_now() }
-        tx1.send(());
-        rx2.recv();
-    }
-
-    #[test]
-    fn stream_data_waiting() {
-        let (tx1, rx1) = channel();
-        let (tx2, rx2) = channel();
-        tx1.send(());
-        tx1.send(());
-        rx1.recv();
-        rx1.recv();
-        let _t = Thread::spawn(move|| {
-            select! {
-                () = rx1.recv() => {}
-            }
-            tx2.send(());
-        });
-
-        for _ in range(0u, 100) { Thread::yield_now() }
-        tx1.send(());
-        rx2.recv();
-    }
-
-    #[test]
-    fn shared_data_waiting() {
-        let (tx1, rx1) = channel();
-        let (tx2, rx2) = channel();
-        drop(tx1.clone());
-        tx1.send(());
-        rx1.recv();
-        let _t = Thread::spawn(move|| {
-            select! {
-                () = rx1.recv() => {}
-            }
-            tx2.send(());
-        });
-
-        for _ in range(0u, 100) { Thread::yield_now() }
-        tx1.send(());
-        rx2.recv();
-    }
-
-    #[test]
-    fn sync1() {
-        let (tx, rx) = sync_channel::<int>(1);
-        tx.send(1);
-        select! {
-            n = rx.recv() => { assert_eq!(n, 1); }
-        }
-    }
-
-    #[test]
-    fn sync2() {
-        let (tx, rx) = sync_channel::<int>(0);
-        let _t = Thread::spawn(move|| {
-            for _ in range(0u, 100) { Thread::yield_now() }
-            tx.send(1);
-        });
-        select! {
-            n = rx.recv() => { assert_eq!(n, 1); }
-        }
-    }
-
-    #[test]
-    fn sync3() {
-        let (tx1, rx1) = sync_channel::<int>(0);
-        let (tx2, rx2): (Sender<int>, Receiver<int>) = channel();
-        let _t = Thread::spawn(move|| { tx1.send(1); });
-        let _t = Thread::spawn(move|| { tx2.send(2); });
-        select! {
-            n = rx1.recv() => {
-                assert_eq!(n, 1);
-                assert_eq!(rx2.recv(), 2);
-            },
-            n = rx2.recv() => {
-                assert_eq!(n, 2);
-                assert_eq!(rx1.recv(), 1);
-            }
-        }
-    }
-}
diff --git a/src/libstd/comm/shared.rs b/src/libstd/comm/shared.rs
deleted file mode 100644 (file)
index 1022694..0000000
+++ /dev/null
@@ -1,486 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/// 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
-/// channels are cloneable allowing for multiple senders.
-///
-/// High level implementation details can be found in the comment of the parent
-/// module. You'll also note that the implementation of the shared and stream
-/// channels are quite similar, and this is no coincidence!
-
-pub use self::Failure::*;
-
-use core::prelude::*;
-
-use core::cmp;
-use core::int;
-
-use sync::{atomic, Mutex, MutexGuard};
-use comm::mpsc_queue as mpsc;
-use comm::blocking::{mod, SignalToken};
-use comm::select::StartResult;
-use comm::select::StartResult::*;
-use thread::Thread;
-
-const DISCONNECTED: int = int::MIN;
-const FUDGE: int = 1024;
-#[cfg(test)]
-const MAX_STEALS: int = 5;
-#[cfg(not(test))]
-const MAX_STEALS: int = 1 << 20;
-
-pub struct Packet<T> {
-    queue: mpsc::Queue<T>,
-    cnt: atomic::AtomicInt, // How many items are on this channel
-    steals: int, // How many times has a port received without blocking?
-    to_wake: atomic::AtomicUint, // SignalToken for wake up
-
-    // The number of channels which are currently using this packet.
-    channels: atomic::AtomicInt,
-
-    // See the discussion in Port::drop and the channel send methods for what
-    // these are used for
-    port_dropped: atomic::AtomicBool,
-    sender_drain: atomic::AtomicInt,
-
-    // this lock protects various portions of this implementation during
-    // select()
-    select_lock: Mutex<()>,
-}
-
-pub enum Failure {
-    Empty,
-    Disconnected,
-}
-
-impl<T: Send> Packet<T> {
-    // Creation of a packet *must* be followed by a call to postinit_lock
-    // and later by inherit_blocker
-    pub fn new() -> Packet<T> {
-        let p = Packet {
-            queue: mpsc::Queue::new(),
-            cnt: atomic::AtomicInt::new(0),
-            steals: 0,
-            to_wake: atomic::AtomicUint::new(0),
-            channels: atomic::AtomicInt::new(2),
-            port_dropped: atomic::AtomicBool::new(false),
-            sender_drain: atomic::AtomicInt::new(0),
-            select_lock: Mutex::new(()),
-        };
-        return p;
-    }
-
-    // This function should be used after newly created Packet
-    // was wrapped with an Arc
-    // 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<()> {
-        self.select_lock.lock()
-    }
-
-    // This function is used at the creation of a shared packet to inherit a
-    // previously blocked task. This is done to prevent spurious wakeups of
-    // tasks in select().
-    //
-    // This can only be called at channel-creation time
-    pub fn inherit_blocker(&mut self,
-                           token: Option<SignalToken>,
-                           guard: MutexGuard<()>) {
-        token.map(|token| {
-            assert_eq!(self.cnt.load(atomic::SeqCst), 0);
-            assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
-            self.to_wake.store(unsafe { token.cast_to_uint() }, atomic::SeqCst);
-            self.cnt.store(-1, atomic::SeqCst);
-
-            // This store is a little sketchy. What's happening here is that
-            // we're transferring a blocker from a oneshot or stream channel to
-            // this shared channel. In doing so, we never spuriously wake them
-            // up and rather only wake them up at the appropriate time. This
-            // implementation of shared channels assumes that any blocking
-            // recv() will undo the increment of steals performed in try_recv()
-            // once the recv is complete.  This thread that we're inheriting,
-            // however, is not in the middle of recv. Hence, the first time we
-            // wake them up, they're going to wake up from their old port, move
-            // on to the upgraded port, and then call the block recv() function.
-            //
-            // When calling this function, they'll find there's data immediately
-            // available, counting it as a steal. This in fact wasn't a steal
-            // because we appropriately blocked them waiting for data.
-            //
-            // To offset this bad increment, we initially set the steal count to
-            // -1. You'll find some special code in abort_selection() as well to
-            // ensure that this -1 steal count doesn't escape too far.
-            self.steals = -1;
-        });
-
-        // When the shared packet is constructed, we grabbed this lock. The
-        // purpose of this lock is to ensure that abort_selection() doesn't
-        // interfere with this method. After we unlock this lock, we're
-        // signifying that we're done modifying self.cnt and self.to_wake and
-        // the port is ready for the world to continue using it.
-        drop(guard);
-    }
-
-    pub fn send(&mut self, t: T) -> Result<(), T> {
-        // See Port::drop for what's going on
-        if self.port_dropped.load(atomic::SeqCst) { return Err(t) }
-
-        // Note that the multiple sender case is a little trickier
-        // semantically than the single sender case. The logic for
-        // incrementing is "add and if disconnected store disconnected".
-        // This could end up leading some senders to believe that there
-        // wasn't a disconnect if in fact there was a disconnect. This means
-        // that while one thread is attempting to re-store the disconnected
-        // states, other threads could walk through merrily incrementing
-        // this very-negative disconnected count. To prevent senders from
-        // spuriously attempting to send when the channels is actually
-        // disconnected, the count has a ranged check here.
-        //
-        // This is also done for another reason. Remember that the return
-        // value of this function is:
-        //
-        //  `true` == the data *may* be received, this essentially has no
-        //            meaning
-        //  `false` == the data will *never* be received, this has a lot of
-        //             meaning
-        //
-        // In the SPSC case, we have a check of 'queue.is_empty()' to see
-        // whether the data was actually received, but this same condition
-        // means nothing in a multi-producer context. As a result, this
-        // preflight check serves as the definitive "this will never be
-        // received". Once we get beyond this check, we have permanently
-        // entered the realm of "this may be received"
-        if self.cnt.load(atomic::SeqCst) < DISCONNECTED + FUDGE {
-            return Err(t)
-        }
-
-        self.queue.push(t);
-        match self.cnt.fetch_add(1, atomic::SeqCst) {
-            -1 => {
-                self.take_to_wake().signal();
-            }
-
-            // In this case, we have possibly failed to send our data, and
-            // we need to consider re-popping the data in order to fully
-            // destroy it. We must arbitrate among the multiple senders,
-            // however, because the queues that we're using are
-            // single-consumer queues. In order to do this, all exiting
-            // pushers will use an atomic count in order to count those
-            // flowing through. Pushers who see 0 are required to drain as
-            // much as possible, and then can only exit when they are the
-            // only pusher (otherwise they must try again).
-            n if n < DISCONNECTED + FUDGE => {
-                // see the comment in 'try' for a shared channel for why this
-                // window of "not disconnected" is ok.
-                self.cnt.store(DISCONNECTED, atomic::SeqCst);
-
-                if self.sender_drain.fetch_add(1, atomic::SeqCst) == 0 {
-                    loop {
-                        // drain the queue, for info on the thread yield see the
-                        // discussion in try_recv
-                        loop {
-                            match self.queue.pop() {
-                                mpsc::Data(..) => {}
-                                mpsc::Empty => break,
-                                mpsc::Inconsistent => Thread::yield_now(),
-                            }
-                        }
-                        // maybe we're done, if we're not the last ones
-                        // here, then we need to go try again.
-                        if self.sender_drain.fetch_sub(1, atomic::SeqCst) == 1 {
-                            break
-                        }
-                    }
-
-                    // At this point, there may still be data on the queue,
-                    // but only if the count hasn't been incremented and
-                    // some other sender hasn't finished pushing data just
-                    // yet. That sender in question will drain its own data.
-                }
-            }
-
-            // Can't make any assumptions about this case like in the SPSC case.
-            _ => {}
-        }
-
-        Ok(())
-    }
-
-    pub fn recv(&mut self) -> Result<T, Failure> {
-        // This code is essentially the exact same as that found in the stream
-        // case (see stream.rs)
-        match self.try_recv() {
-            Err(Empty) => {}
-            data => return data,
-        }
-
-        let (wait_token, signal_token) = blocking::tokens();
-        if self.decrement(signal_token) == Installed {
-            wait_token.wait()
-        }
-
-        match self.try_recv() {
-            data @ Ok(..) => { self.steals -= 1; data }
-            data => data,
-        }
-    }
-
-    // Essentially the exact same thing as the stream decrement function.
-    // Returns true if blocking should proceed.
-    fn decrement(&mut self, token: SignalToken) -> StartResult {
-        assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
-        let ptr = unsafe { token.cast_to_uint() };
-        self.to_wake.store(ptr, atomic::SeqCst);
-
-        let steals = self.steals;
-        self.steals = 0;
-
-        match self.cnt.fetch_sub(1 + steals, atomic::SeqCst) {
-            DISCONNECTED => { self.cnt.store(DISCONNECTED, atomic::SeqCst); }
-            // If we factor in our steals and notice that the channel has no
-            // data, we successfully sleep
-            n => {
-                assert!(n >= 0);
-                if n - steals <= 0 { return Installed }
-            }
-        }
-
-        self.to_wake.store(0, atomic::SeqCst);
-        drop(unsafe { SignalToken::cast_from_uint(ptr) });
-        Abort
-    }
-
-    pub fn try_recv(&mut self) -> Result<T, Failure> {
-        let ret = match self.queue.pop() {
-            mpsc::Data(t) => Some(t),
-            mpsc::Empty => None,
-
-            // This is a bit of an interesting case. The channel is reported as
-            // having data available, but our pop() has failed due to the queue
-            // being in an inconsistent state.  This means that there is some
-            // pusher somewhere which has yet to complete, but we are guaranteed
-            // that a pop will eventually succeed. In this case, we spin in a
-            // yield loop because the remote sender should finish their enqueue
-            // operation "very quickly".
-            //
-            // Avoiding this yield loop would require a different queue
-            // abstraction which provides the guarantee that after M pushes have
-            // succeeded, at least M pops will succeed. The current queues
-            // guarantee that if there are N active pushes, you can pop N times
-            // once all N have finished.
-            mpsc::Inconsistent => {
-                let data;
-                loop {
-                    Thread::yield_now();
-                    match self.queue.pop() {
-                        mpsc::Data(t) => { data = t; break }
-                        mpsc::Empty => panic!("inconsistent => empty"),
-                        mpsc::Inconsistent => {}
-                    }
-                }
-                Some(data)
-            }
-        };
-        match ret {
-            // See the discussion in the stream implementation for why we
-            // might decrement steals.
-            Some(data) => {
-                if self.steals > MAX_STEALS {
-                    match self.cnt.swap(0, atomic::SeqCst) {
-                        DISCONNECTED => {
-                            self.cnt.store(DISCONNECTED, atomic::SeqCst);
-                        }
-                        n => {
-                            let m = cmp::min(n, self.steals);
-                            self.steals -= m;
-                            self.bump(n - m);
-                        }
-                    }
-                    assert!(self.steals >= 0);
-                }
-                self.steals += 1;
-                Ok(data)
-            }
-
-            // See the discussion in the stream implementation for why we try
-            // again.
-            None => {
-                match self.cnt.load(atomic::SeqCst) {
-                    n if n != DISCONNECTED => Err(Empty),
-                    _ => {
-                        match self.queue.pop() {
-                            mpsc::Data(t) => Ok(t),
-                            mpsc::Empty => Err(Disconnected),
-                            // with no senders, an inconsistency is impossible.
-                            mpsc::Inconsistent => unreachable!(),
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    // Prepares this shared packet for a channel clone, essentially just bumping
-    // a refcount.
-    pub fn clone_chan(&mut self) {
-        self.channels.fetch_add(1, atomic::SeqCst);
-    }
-
-    // Decrement the reference count on a channel. This is called whenever a
-    // Chan is dropped and may end up waking up a receiver. It's the receiver's
-    // responsibility on the other end to figure out that we've disconnected.
-    pub fn drop_chan(&mut self) {
-        match self.channels.fetch_sub(1, atomic::SeqCst) {
-            1 => {}
-            n if n > 1 => return,
-            n => panic!("bad number of channels left {}", n),
-        }
-
-        match self.cnt.swap(DISCONNECTED, atomic::SeqCst) {
-            -1 => { self.take_to_wake().signal(); }
-            DISCONNECTED => {}
-            n => { assert!(n >= 0); }
-        }
-    }
-
-    // See the long discussion inside of stream.rs for why the queue is drained,
-    // and why it is done in this fashion.
-    pub fn drop_port(&mut self) {
-        self.port_dropped.store(true, atomic::SeqCst);
-        let mut steals = self.steals;
-        while {
-            let cnt = self.cnt.compare_and_swap(steals, DISCONNECTED, atomic::SeqCst);
-            cnt != DISCONNECTED && cnt != steals
-        } {
-            // See the discussion in 'try_recv' for why we yield
-            // control of this thread.
-            loop {
-                match self.queue.pop() {
-                    mpsc::Data(..) => { steals += 1; }
-                    mpsc::Empty | mpsc::Inconsistent => break,
-                }
-            }
-        }
-    }
-
-    // Consumes ownership of the 'to_wake' field.
-    fn take_to_wake(&mut self) -> SignalToken {
-        let ptr = self.to_wake.load(atomic::SeqCst);
-        self.to_wake.store(0, atomic::SeqCst);
-        assert!(ptr != 0);
-        unsafe { SignalToken::cast_from_uint(ptr) }
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    // 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(&mut self) -> bool {
-        let cnt = self.cnt.load(atomic::SeqCst);
-        cnt == DISCONNECTED || cnt - self.steals > 0
-    }
-
-    // increment the count on the channel (used for selection)
-    fn bump(&mut self, amt: int) -> int {
-        match self.cnt.fetch_add(amt, atomic::SeqCst) {
-            DISCONNECTED => {
-                self.cnt.store(DISCONNECTED, atomic::SeqCst);
-                DISCONNECTED
-            }
-            n => n
-        }
-    }
-
-    // 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(&mut 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 task waiting on this port, returning whether there's
-    // data on the port.
-    //
-    // This is similar to the stream implementation (hence fewer comments), but
-    // uses a different value for the "steals" variable.
-    pub fn abort_selection(&mut self, _was_upgrade: bool) -> bool {
-        // Before we do anything else, we bounce on this lock. The reason for
-        // doing this is to ensure that any upgrade-in-progress is gone and
-        // done with. Without this bounce, we can race with inherit_blocker
-        // about looking at and dealing with to_wake. Once we have acquired the
-        // lock, we are guaranteed that inherit_blocker is done.
-        {
-            let _guard = self.select_lock.lock();
-        }
-
-        // Like the stream implementation, we want to make sure that the count
-        // on the channel goes non-negative. We don't know how negative the
-        // stream currently is, so instead of using a steal value of 1, we load
-        // the channel count and figure out what we should do to make it
-        // positive.
-        let steals = {
-            let cnt = self.cnt.load(atomic::SeqCst);
-            if cnt < 0 && cnt != DISCONNECTED {-cnt} else {0}
-        };
-        let prev = self.bump(steals + 1);
-
-        if prev == DISCONNECTED {
-            assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
-            true
-        } else {
-            let cur = prev + steals + 1;
-            assert!(cur >= 0);
-            if prev < 0 {
-                drop(self.take_to_wake());
-            } else {
-                while self.to_wake.load(atomic::SeqCst) != 0 {
-                    Thread::yield_now();
-                }
-            }
-            // if the number of steals is -1, it was the pre-emptive -1 steal
-            // count from when we inherited a blocker. This is fine because
-            // we're just going to overwrite it with a real value.
-            assert!(self.steals == 0 || self.steals == -1);
-            self.steals = steals;
-            prev >= 0
-        }
-    }
-}
-
-#[unsafe_destructor]
-impl<T: Send> Drop for Packet<T> {
-    fn drop(&mut self) {
-        // Note that this load is not only an assert for correctness about
-        // disconnection, but also a proper fence before the read of
-        // `to_wake`, so this assert cannot be removed with also removing
-        // the `to_wake` assert.
-        assert_eq!(self.cnt.load(atomic::SeqCst), DISCONNECTED);
-        assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
-        assert_eq!(self.channels.load(atomic::SeqCst), 0);
-    }
-}
diff --git a/src/libstd/comm/spsc_queue.rs b/src/libstd/comm/spsc_queue.rs
deleted file mode 100644 (file)
index 1e2f522..0000000
+++ /dev/null
@@ -1,343 +0,0 @@
-/* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *    1. Redistributions of source code must retain the above copyright notice,
- *       this list of conditions and the following disclaimer.
- *
- *    2. Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
- * SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are
- * those of the authors and should not be interpreted as representing official
- * policies, either expressed or implied, of Dmitry Vyukov.
- */
-
-// http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
-
-//! A single-producer single-consumer concurrent queue
-//!
-//! This module contains the implementation of an SPSC queue which can be used
-//! concurrently between two tasks. This data structure is safe to use and
-//! enforces the semantics that there is one pusher and one popper.
-
-#![experimental]
-
-use core::prelude::*;
-
-use alloc::boxed::Box;
-use core::mem;
-use core::cell::UnsafeCell;
-
-use sync::atomic::{AtomicPtr, Relaxed, AtomicUint, Acquire, Release};
-
-// Node within the linked list queue of messages to send
-struct Node<T> {
-    // FIXME: this could be an uninitialized T if we're careful enough, and
-    //      that would reduce memory usage (and be a bit faster).
-    //      is it worth it?
-    value: Option<T>,           // nullable for re-use of nodes
-    next: AtomicPtr<Node<T>>,   // next node in the queue
-}
-
-/// The single-producer single-consumer queue. This structure is not cloneable,
-/// but it can be safely shared in an Arc if it is guaranteed that there
-/// is only one popper and one pusher touching the queue at any one point in
-/// time.
-pub struct Queue<T> {
-    // consumer fields
-    tail: UnsafeCell<*mut Node<T>>, // where to pop from
-    tail_prev: AtomicPtr<Node<T>>, // where to pop from
-
-    // producer fields
-    head: UnsafeCell<*mut Node<T>>,      // where to push to
-    first: UnsafeCell<*mut Node<T>>,     // where to get new nodes from
-    tail_copy: UnsafeCell<*mut Node<T>>, // between first/tail
-
-    // Cache maintenance fields. Additions and subtractions are stored
-    // separately in order to allow them to use nonatomic addition/subtraction.
-    cache_bound: uint,
-    cache_additions: AtomicUint,
-    cache_subtractions: AtomicUint,
-}
-
-unsafe impl<T: Send> Send for Queue<T> { }
-
-unsafe impl<T: Send> Sync for Queue<T> { }
-
-impl<T: Send> Node<T> {
-    fn new() -> *mut Node<T> {
-        unsafe {
-            mem::transmute(box Node {
-                value: None,
-                next: AtomicPtr::new(0 as *mut Node<T>),
-            })
-        }
-    }
-}
-
-impl<T: Send> Queue<T> {
-    /// Creates a new queue.
-    ///
-    /// This is unsafe as the type system doesn't enforce a single
-    /// consumer-producer relationship. It also allows the consumer to `pop`
-    /// items while there is a `peek` active due to all methods having a
-    /// non-mutable receiver.
-    ///
-    /// # Arguments
-    ///
-    ///   * `bound` - This queue implementation is implemented with a linked
-    ///               list, and this means that a push is always a malloc. In
-    ///               order to amortize this cost, an internal cache of nodes is
-    ///               maintained to prevent a malloc from always being
-    ///               necessary. This bound is the limit on the size of the
-    ///               cache (if desired). If the value is 0, then the cache has
-    ///               no bound. Otherwise, the cache will never grow larger than
-    ///               `bound` (although the queue itself could be much larger.
-    pub unsafe fn new(bound: uint) -> Queue<T> {
-        let n1 = Node::new();
-        let n2 = Node::new();
-        (*n1).next.store(n2, Relaxed);
-        Queue {
-            tail: UnsafeCell::new(n2),
-            tail_prev: AtomicPtr::new(n1),
-            head: UnsafeCell::new(n2),
-            first: UnsafeCell::new(n1),
-            tail_copy: UnsafeCell::new(n1),
-            cache_bound: bound,
-            cache_additions: AtomicUint::new(0),
-            cache_subtractions: AtomicUint::new(0),
-        }
-    }
-
-    /// Pushes a new value onto this queue. Note that to use this function
-    /// safely, it must be externally guaranteed that there is only one pusher.
-    pub fn push(&self, t: T) {
-        unsafe {
-            // Acquire a node (which either uses a cached one or allocates a new
-            // one), and then append this to the 'head' node.
-            let n = self.alloc();
-            assert!((*n).value.is_none());
-            (*n).value = Some(t);
-            (*n).next.store(0 as *mut Node<T>, Relaxed);
-            (**self.head.get()).next.store(n, Release);
-            *self.head.get() = n;
-        }
-    }
-
-    unsafe fn alloc(&self) -> *mut Node<T> {
-        // First try to see if we can consume the 'first' node for our uses.
-        // We try to avoid as many atomic instructions as possible here, so
-        // the addition to cache_subtractions is not atomic (plus we're the
-        // only one subtracting from the cache).
-        if *self.first.get() != *self.tail_copy.get() {
-            if self.cache_bound > 0 {
-                let b = self.cache_subtractions.load(Relaxed);
-                self.cache_subtractions.store(b + 1, Relaxed);
-            }
-            let ret = *self.first.get();
-            *self.first.get() = (*ret).next.load(Relaxed);
-            return ret;
-        }
-        // If the above fails, then update our copy of the tail and try
-        // again.
-        *self.tail_copy.get() = self.tail_prev.load(Acquire);
-        if *self.first.get() != *self.tail_copy.get() {
-            if self.cache_bound > 0 {
-                let b = self.cache_subtractions.load(Relaxed);
-                self.cache_subtractions.store(b + 1, Relaxed);
-            }
-            let ret = *self.first.get();
-            *self.first.get() = (*ret).next.load(Relaxed);
-            return ret;
-        }
-        // If all of that fails, then we have to allocate a new node
-        // (there's nothing in the node cache).
-        Node::new()
-    }
-
-    /// Attempts to pop a value from this queue. Remember that to use this type
-    /// safely you must ensure that there is only one popper at a time.
-    pub fn pop(&self) -> Option<T> {
-        unsafe {
-            // The `tail` node is not actually a used node, but rather a
-            // sentinel from where we should start popping from. Hence, look at
-            // tail's next field and see if we can use it. If we do a pop, then
-            // the current tail node is a candidate for going into the cache.
-            let tail = *self.tail.get();
-            let next = (*tail).next.load(Acquire);
-            if next.is_null() { return None }
-            assert!((*next).value.is_some());
-            let ret = (*next).value.take();
-
-            *self.tail.get() = next;
-            if self.cache_bound == 0 {
-                self.tail_prev.store(tail, Release);
-            } else {
-                // FIXME: this is dubious with overflow.
-                let additions = self.cache_additions.load(Relaxed);
-                let subtractions = self.cache_subtractions.load(Relaxed);
-                let size = additions - subtractions;
-
-                if size < self.cache_bound {
-                    self.tail_prev.store(tail, Release);
-                    self.cache_additions.store(additions + 1, Relaxed);
-                } else {
-                    (*self.tail_prev.load(Relaxed)).next.store(next, Relaxed);
-                    // We have successfully erased all references to 'tail', so
-                    // now we can safely drop it.
-                    let _: Box<Node<T>> = mem::transmute(tail);
-                }
-            }
-            return ret;
-        }
-    }
-
-    /// Attempts to peek at the head of the queue, returning `None` if the queue
-    /// has no data currently
-    ///
-    /// # Warning
-    /// The reference returned is invalid if it is not used before the consumer
-    /// pops the value off the queue. If the producer then pushes another value
-    /// onto the queue, it will overwrite the value pointed to by the reference.
-    pub fn peek<'a>(&'a self) -> Option<&'a mut T> {
-        // This is essentially the same as above with all the popping bits
-        // stripped out.
-        unsafe {
-            let tail = *self.tail.get();
-            let next = (*tail).next.load(Acquire);
-            if next.is_null() { return None }
-            return (*next).value.as_mut();
-        }
-    }
-}
-
-#[unsafe_destructor]
-impl<T: Send> Drop for Queue<T> {
-    fn drop(&mut self) {
-        unsafe {
-            let mut cur = *self.first.get();
-            while !cur.is_null() {
-                let next = (*cur).next.load(Relaxed);
-                let _n: Box<Node<T>> = mem::transmute(cur);
-                cur = next;
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use prelude::v1::*;
-
-    use sync::Arc;
-    use super::Queue;
-    use thread::Thread;
-    use comm::channel;
-
-    #[test]
-    fn smoke() {
-        unsafe {
-            let queue = Queue::new(0);
-            queue.push(1i);
-            queue.push(2);
-            assert_eq!(queue.pop(), Some(1i));
-            assert_eq!(queue.pop(), Some(2));
-            assert_eq!(queue.pop(), None);
-            queue.push(3);
-            queue.push(4);
-            assert_eq!(queue.pop(), Some(3));
-            assert_eq!(queue.pop(), Some(4));
-            assert_eq!(queue.pop(), None);
-        }
-    }
-
-    #[test]
-    fn peek() {
-        unsafe {
-            let queue = Queue::new(0);
-            queue.push(vec![1i]);
-
-            // Ensure the borrowchecker works
-            match queue.peek() {
-                Some(vec) => match vec.as_slice() {
-                    // Note that `pop` is not allowed here due to borrow
-                    [1] => {}
-                    _ => return
-                },
-                None => unreachable!()
-            }
-
-            queue.pop();
-        }
-    }
-
-    #[test]
-    fn drop_full() {
-        unsafe {
-            let q = Queue::new(0);
-            q.push(box 1i);
-            q.push(box 2i);
-        }
-    }
-
-    #[test]
-    fn smoke_bound() {
-        unsafe {
-            let q = Queue::new(0);
-            q.push(1i);
-            q.push(2);
-            assert_eq!(q.pop(), Some(1));
-            assert_eq!(q.pop(), Some(2));
-            assert_eq!(q.pop(), None);
-            q.push(3);
-            q.push(4);
-            assert_eq!(q.pop(), Some(3));
-            assert_eq!(q.pop(), Some(4));
-            assert_eq!(q.pop(), None);
-        }
-    }
-
-    #[test]
-    fn stress() {
-        unsafe {
-            stress_bound(0);
-            stress_bound(1);
-        }
-
-        unsafe fn stress_bound(bound: uint) {
-            let q = Arc::new(Queue::new(bound));
-
-            let (tx, rx) = channel();
-            let q2 = q.clone();
-            let _t = Thread::spawn(move|| {
-                for _ in range(0u, 100000) {
-                    loop {
-                        match q2.pop() {
-                            Some(1i) => break,
-                            Some(_) => panic!(),
-                            None => {}
-                        }
-                    }
-                }
-                tx.send(());
-            });
-            for _ in range(0i, 100000) {
-                q.push(1);
-            }
-            rx.recv();
-        }
-    }
-}
diff --git a/src/libstd/comm/stream.rs b/src/libstd/comm/stream.rs
deleted file mode 100644 (file)
index b68f626..0000000
+++ /dev/null
@@ -1,484 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/// Stream channels
-///
-/// This is the flavor of channels which are optimized for one sender and one
-/// receiver. The sender will be upgraded to a shared channel if the channel is
-/// cloned.
-///
-/// High level implementation details can be found in the comment of the parent
-/// module.
-
-pub use self::Failure::*;
-pub use self::UpgradeResult::*;
-pub use self::SelectionResult::*;
-use self::Message::*;
-
-use core::prelude::*;
-
-use core::cmp;
-use core::int;
-use thread::Thread;
-
-use sync::atomic;
-use comm::spsc_queue as spsc;
-use comm::Receiver;
-use comm::blocking::{mod, SignalToken};
-
-const DISCONNECTED: int = int::MIN;
-#[cfg(test)]
-const MAX_STEALS: int = 5;
-#[cfg(not(test))]
-const MAX_STEALS: int = 1 << 20;
-
-pub struct Packet<T> {
-    queue: spsc::Queue<Message<T>>, // internal queue for all message
-
-    cnt: atomic::AtomicInt, // How many items are on this channel
-    steals: int, // How many times has a port received without blocking?
-    to_wake: atomic::AtomicUint, // SignalToken for the blocked thread to wake up
-
-    port_dropped: atomic::AtomicBool, // flag if the channel has been destroyed.
-}
-
-pub enum Failure<T> {
-    Empty,
-    Disconnected,
-    Upgraded(Receiver<T>),
-}
-
-pub enum UpgradeResult {
-    UpSuccess,
-    UpDisconnected,
-    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> {
-    Data(T),
-    GoUp(Receiver<T>),
-}
-
-impl<T: Send> Packet<T> {
-    pub fn new() -> Packet<T> {
-        Packet {
-            queue: unsafe { spsc::Queue::new(128) },
-
-            cnt: atomic::AtomicInt::new(0),
-            steals: 0,
-            to_wake: atomic::AtomicUint::new(0),
-
-            port_dropped: atomic::AtomicBool::new(false),
-        }
-    }
-
-    pub fn send(&mut self, t: T) -> Result<(), T> {
-        // If the other port has deterministically gone away, then definitely
-        // must return the data back up the stack. Otherwise, the data is
-        // considered as being sent.
-        if self.port_dropped.load(atomic::SeqCst) { return Err(t) }
-
-        match self.do_send(Data(t)) {
-            UpSuccess | UpDisconnected => {},
-            UpWoke(token) => { token.signal(); }
-        }
-        Ok(())
-    }
-
-    pub fn upgrade(&mut self, up: Receiver<T>) -> UpgradeResult {
-        // If the port has gone away, then there's no need to proceed any
-        // further.
-        if self.port_dropped.load(atomic::SeqCst) { return UpDisconnected }
-
-        self.do_send(GoUp(up))
-    }
-
-    fn do_send(&mut self, t: Message<T>) -> UpgradeResult {
-        self.queue.push(t);
-        match self.cnt.fetch_add(1, atomic::SeqCst) {
-            // As described in the mod's doc comment, -1 == wakeup
-            -1 => UpWoke(self.take_to_wake()),
-            // As as described before, SPSC queues must be >= -2
-            -2 => UpSuccess,
-
-            // Be sure to preserve the disconnected state, and the return value
-            // in this case is going to be whether our data was received or not.
-            // This manifests itself on whether we have an empty queue or not.
-            //
-            // Primarily, are required to drain the queue here because the port
-            // will never remove this data. We can only have at most one item to
-            // drain (the port drains the rest).
-            DISCONNECTED => {
-                self.cnt.store(DISCONNECTED, atomic::SeqCst);
-                let first = self.queue.pop();
-                let second = self.queue.pop();
-                assert!(second.is_none());
-
-                match first {
-                    Some(..) => UpSuccess,  // we failed to send the data
-                    None => UpDisconnected, // we successfully sent data
-                }
-            }
-
-            // Otherwise we just sent some data on a non-waiting queue, so just
-            // make sure the world is sane and carry on!
-            n => { assert!(n >= 0); UpSuccess }
-        }
-    }
-
-    // Consumes ownership of the 'to_wake' field.
-    fn take_to_wake(&mut self) -> SignalToken {
-        let ptr = self.to_wake.load(atomic::SeqCst);
-        self.to_wake.store(0, atomic::SeqCst);
-        assert!(ptr != 0);
-        unsafe { SignalToken::cast_from_uint(ptr) }
-    }
-
-    // Decrements the count on the channel for a sleeper, returning the sleeper
-    // back if it shouldn't sleep. Note that this is the location where we take
-    // steals into account.
-    fn decrement(&mut self, token: SignalToken) -> Result<(), SignalToken> {
-        assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
-        let ptr = unsafe { token.cast_to_uint() };
-        self.to_wake.store(ptr, atomic::SeqCst);
-
-        let steals = self.steals;
-        self.steals = 0;
-
-        match self.cnt.fetch_sub(1 + steals, atomic::SeqCst) {
-            DISCONNECTED => { self.cnt.store(DISCONNECTED, atomic::SeqCst); }
-            // If we factor in our steals and notice that the channel has no
-            // data, we successfully sleep
-            n => {
-                assert!(n >= 0);
-                if n - steals <= 0 { return Ok(()) }
-            }
-        }
-
-        self.to_wake.store(0, atomic::SeqCst);
-        Err(unsafe { SignalToken::cast_from_uint(ptr) })
-    }
-
-    pub fn recv(&mut self) -> Result<T, Failure<T>> {
-        // Optimistic preflight check (scheduling is expensive).
-        match self.try_recv() {
-            Err(Empty) => {}
-            data => return data,
-        }
-
-        // Welp, our channel has no data. Deschedule the current task and
-        // initiate the blocking protocol.
-        let (wait_token, signal_token) = blocking::tokens();
-        if self.decrement(signal_token).is_ok() {
-            wait_token.wait()
-        }
-
-        match self.try_recv() {
-            // Messages which actually popped from the queue shouldn't count as
-            // a steal, so offset the decrement here (we already have our
-            // "steal" factored into the channel count above).
-            data @ Ok(..) |
-            data @ Err(Upgraded(..)) => {
-                self.steals -= 1;
-                data
-            }
-
-            data => data,
-        }
-    }
-
-    pub fn try_recv(&mut self) -> Result<T, Failure<T>> {
-        match self.queue.pop() {
-            // If we stole some data, record to that effect (this will be
-            // factored into cnt later on).
-            //
-            // Note that we don't allow steals to grow without bound in order to
-            // prevent eventual overflow of either steals or cnt as an overflow
-            // would have catastrophic results. Sometimes, steals > cnt, but
-            // other times cnt > steals, so we don't know the relation between
-            // steals and cnt. This code path is executed only rarely, so we do
-            // a pretty slow operation, of swapping 0 into cnt, taking steals
-            // down as much as possible (without going negative), and then
-            // adding back in whatever we couldn't factor into steals.
-            Some(data) => {
-                if self.steals > MAX_STEALS {
-                    match self.cnt.swap(0, atomic::SeqCst) {
-                        DISCONNECTED => {
-                            self.cnt.store(DISCONNECTED, atomic::SeqCst);
-                        }
-                        n => {
-                            let m = cmp::min(n, self.steals);
-                            self.steals -= m;
-                            self.bump(n - m);
-                        }
-                    }
-                    assert!(self.steals >= 0);
-                }
-                self.steals += 1;
-                match data {
-                    Data(t) => Ok(t),
-                    GoUp(up) => Err(Upgraded(up)),
-                }
-            }
-
-            None => {
-                match self.cnt.load(atomic::SeqCst) {
-                    n if n != DISCONNECTED => Err(Empty),
-
-                    // This is a little bit of a tricky case. We failed to pop
-                    // data above, and then we have viewed that the channel is
-                    // disconnected. In this window more data could have been
-                    // sent on the channel. It doesn't really make sense to
-                    // return that the channel is disconnected when there's
-                    // actually data on it, so be extra sure there's no data by
-                    // popping one more time.
-                    //
-                    // We can ignore steals because the other end is
-                    // disconnected and we'll never need to really factor in our
-                    // steals again.
-                    _ => {
-                        match self.queue.pop() {
-                            Some(Data(t)) => Ok(t),
-                            Some(GoUp(up)) => Err(Upgraded(up)),
-                            None => Err(Disconnected),
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    pub fn drop_chan(&mut self) {
-        // Dropping a channel is pretty simple, we just flag it as disconnected
-        // and then wakeup a blocker if there is one.
-        match self.cnt.swap(DISCONNECTED, atomic::SeqCst) {
-            -1 => { self.take_to_wake().signal(); }
-            DISCONNECTED => {}
-            n => { assert!(n >= 0); }
-        }
-    }
-
-    pub fn drop_port(&mut self) {
-        // Dropping a port seems like a fairly trivial thing. In theory all we
-        // need to do is flag that we're disconnected and then everything else
-        // can take over (we don't have anyone to wake up).
-        //
-        // The catch for Ports is that we want to drop the entire contents of
-        // the queue. There are multiple reasons for having this property, the
-        // largest of which is that if another chan is waiting in this channel
-        // (but not received yet), then waiting on that port will cause a
-        // deadlock.
-        //
-        // So if we accept that we must now destroy the entire contents of the
-        // queue, this code may make a bit more sense. The tricky part is that
-        // we can't let any in-flight sends go un-dropped, we have to make sure
-        // *everything* is dropped and nothing new will come onto the channel.
-
-        // The first thing we do is set a flag saying that we're done for. All
-        // sends are gated on this flag, so we're immediately guaranteed that
-        // there are a bounded number of active sends that we'll have to deal
-        // with.
-        self.port_dropped.store(true, atomic::SeqCst);
-
-        // Now that we're guaranteed to deal with a bounded number of senders,
-        // we need to drain the queue. This draining process happens atomically
-        // with respect to the "count" of the channel. If the count is nonzero
-        // (with steals taken into account), then there must be data on the
-        // channel. In this case we drain everything and then try again. We will
-        // continue to fail while active senders send data while we're dropping
-        // data, but eventually we're guaranteed to break out of this loop
-        // (because there is a bounded number of senders).
-        let mut steals = self.steals;
-        while {
-            let cnt = self.cnt.compare_and_swap(
-                            steals, DISCONNECTED, atomic::SeqCst);
-            cnt != DISCONNECTED && cnt != steals
-        } {
-            loop {
-                match self.queue.pop() {
-                    Some(..) => { steals += 1; }
-                    None => break
-                }
-            }
-        }
-
-        // At this point in time, we have gated all future senders from sending,
-        // and we have flagged the channel as being disconnected. The senders
-        // still have some responsibility, however, because some sends may not
-        // complete until after we flag the disconnection. There are more
-        // details in the sending methods that see DISCONNECTED
-    }
-
-    ////////////////////////////////////////////////////////////////////////////
-    // 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(&mut 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(&GoUp(..)) => {
-                match self.recv() {
-                    Err(Upgraded(port)) => Err(port),
-                    _ => unreachable!(),
-                }
-            }
-            Some(..) => Ok(true),
-            None => Ok(false)
-        }
-    }
-
-    // increment the count on the channel (used for selection)
-    fn bump(&mut self, amt: int) -> int {
-        match self.cnt.fetch_add(amt, atomic::SeqCst) {
-            DISCONNECTED => {
-                self.cnt.store(DISCONNECTED, atomic::SeqCst);
-                DISCONNECTED
-            }
-            n => n
-        }
-    }
-
-    // Attempts to start selecting on this port. Like a oneshot, this can fail
-    // immediately because of an upgrade.
-    pub fn start_selection(&mut self, token: SignalToken) -> SelectionResult<T> {
-        match self.decrement(token) {
-            Ok(()) => SelSuccess,
-            Err(token) => {
-                let ret = match self.queue.peek() {
-                    Some(&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);
-                return ret;
-            }
-        }
-    }
-
-    // Removes a previous task from being blocked in this port
-    pub fn abort_selection(&mut self,
-                           was_upgrade: bool) -> Result<bool, Receiver<T>> {
-        // If we're aborting selection after upgrading from a oneshot, then
-        // we're guarantee that no one is waiting. The only way that we could
-        // have seen the upgrade is if data was actually sent on the channel
-        // half again. For us, this means that there is guaranteed to be data on
-        // this channel. Furthermore, we're guaranteed that there was no
-        // start_selection previously, so there's no need to modify `self.cnt`
-        // at all.
-        //
-        // Hence, because of these invariants, we immediately return `Ok(true)`.
-        // Note that the data may not actually be sent on the channel just yet.
-        // The other end could have flagged the upgrade but not sent data to
-        // this end. This is fine because we know it's a small bounded windows
-        // of time until the data is actually sent.
-        if was_upgrade {
-            assert_eq!(self.steals, 0);
-            assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
-            return Ok(true)
-        }
-
-        // We want to make sure that the count on the channel goes non-negative,
-        // and in the stream case we can have at most one steal, so just assume
-        // that we had one steal.
-        let steals = 1;
-        let prev = self.bump(steals + 1);
-
-        // If we were previously disconnected, then we know for sure that there
-        // is no task in to_wake, so just keep going
-        let has_data = if prev == DISCONNECTED {
-            assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
-            true // there is data, that data is that we're disconnected
-        } else {
-            let cur = prev + steals + 1;
-            assert!(cur >= 0);
-
-            // If the previous count was negative, then we just made things go
-            // positive, hence we passed the -1 boundary and we're responsible
-            // for removing the to_wake() field and trashing it.
-            //
-            // If the previous count was positive then we're in a tougher
-            // situation. A possible race is that a sender just incremented
-            // through -1 (meaning it's going to try to wake a task up), but it
-            // hasn't yet read the to_wake. In order to prevent a future recv()
-            // from waking up too early (this sender picking up the plastered
-            // over to_wake), we spin loop here waiting for to_wake to be 0.
-            // Note that this entire select() implementation needs an overhaul,
-            // and this is *not* the worst part of it, so this is not done as a
-            // final solution but rather out of necessity for now to get
-            // something working.
-            if prev < 0 {
-                drop(self.take_to_wake());
-            } else {
-                while self.to_wake.load(atomic::SeqCst) != 0 {
-                    Thread::yield_now();
-                }
-            }
-            assert_eq!(self.steals, 0);
-            self.steals = steals;
-
-            // if we were previously positive, then there's surely data to
-            // receive
-            prev >= 0
-        };
-
-        // Now that we've determined that this queue "has data", we peek at the
-        // queue to see if the data is an upgrade or not. If it's an upgrade,
-        // then we need to destroy this port and abort selection on the
-        // upgraded port.
-        if has_data {
-            match self.queue.peek() {
-                Some(&GoUp(..)) => {
-                    match self.queue.pop() {
-                        Some(GoUp(port)) => Err(port),
-                        _ => unreachable!(),
-                    }
-                }
-                _ => Ok(true),
-            }
-        } else {
-            Ok(false)
-        }
-    }
-}
-
-#[unsafe_destructor]
-impl<T: Send> Drop for Packet<T> {
-    fn drop(&mut self) {
-        // Note that this load is not only an assert for correctness about
-        // disconnection, but also a proper fence before the read of
-        // `to_wake`, so this assert cannot be removed with also removing
-        // the `to_wake` assert.
-        assert_eq!(self.cnt.load(atomic::SeqCst), DISCONNECTED);
-        assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
-    }
-}
diff --git a/src/libstd/comm/sync.rs b/src/libstd/comm/sync.rs
deleted file mode 100644 (file)
index 8833884..0000000
+++ /dev/null
@@ -1,483 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/// Synchronous channels/ports
-///
-/// This channel implementation differs significantly from the asynchronous
-/// implementations found next to it (oneshot/stream/share). This is an
-/// implementation of a synchronous, bounded buffer channel.
-///
-/// Each channel is created with some amount of backing buffer, and sends will
-/// *block* until buffer space becomes available. A buffer size of 0 is valid,
-/// which means that every successful send is paired with a successful recv.
-///
-/// This flavor of channels defines a new `send_opt` method for channels which
-/// is the method by which a message is sent but the task does not panic if it
-/// cannot be delivered.
-///
-/// Another major difference is that send() will *always* return back the data
-/// if it couldn't be sent. This is because it is deterministically known when
-/// the data is received and when it is not received.
-///
-/// Implementation-wise, it can all be summed up with "use a mutex plus some
-/// logic". The mutex used here is an OS native mutex, meaning that no user code
-/// is run inside of the mutex (to prevent context switching). This
-/// implementation shares almost all code for the buffered and unbuffered cases
-/// of a synchronous channel. There are a few branches for the unbuffered case,
-/// but they're mostly just relevant to blocking senders.
-
-use core::prelude::*;
-
-pub use self::Failure::*;
-use self::Blocker::*;
-
-use vec::Vec;
-use core::mem;
-
-use sync::{atomic, Mutex, MutexGuard};
-use comm::blocking::{mod, WaitToken, SignalToken};
-use comm::select::StartResult::{mod, Installed, Abort};
-
-pub struct Packet<T> {
-    /// Only field outside of the mutex. Just done for kicks, but mainly because
-    /// the other shared channel already had the code implemented
-    channels: atomic::AtomicUint,
-
-    lock: Mutex<State<T>>,
-}
-
-unsafe impl<T:Send> Send for Packet<T> { }
-
-unsafe impl<T:Send> Sync for Packet<T> { }
-
-struct State<T> {
-    disconnected: bool, // Is the channel disconnected yet?
-    queue: Queue,       // queue of senders waiting to send data
-    blocker: Blocker,   // currently blocked task on this channel
-    buf: Buffer<T>,     // storage for buffered messages
-    cap: uint,          // capacity of this channel
-
-    /// A curious flag used to indicate whether a sender failed or succeeded in
-    /// blocking. This is used to transmit information back to the task that it
-    /// must dequeue its message from the buffer because it was not received.
-    /// This is only relevant in the 0-buffer case. This obviously cannot be
-    /// safely constructed, but it's guaranteed to always have a valid pointer
-    /// value.
-    canceled: Option<&'static mut bool>,
-}
-
-unsafe impl<T: Send> Send for State<T> {}
-
-/// Possible flavors of threads who can be blocked on this channel.
-enum Blocker {
-    BlockedSender(SignalToken),
-    BlockedReceiver(SignalToken),
-    NoneBlocked
-}
-
-/// Simple queue for threading tasks together. Nodes are stack-allocated, so
-/// this structure is not safe at all
-struct Queue {
-    head: *mut Node,
-    tail: *mut Node,
-}
-
-struct Node {
-    token: Option<SignalToken>,
-    next: *mut Node,
-}
-
-unsafe impl Send for Node {}
-
-/// A simple ring-buffer
-struct Buffer<T> {
-    buf: Vec<Option<T>>,
-    start: uint,
-    size: uint,
-}
-
-#[deriving(Show)]
-pub enum Failure {
-    Empty,
-    Disconnected,
-}
-
-/// Atomically blocks the current thread, placing it into `slot`, unlocking `lock`
-/// in the meantime. This re-locks the mutex upon returning.
-fn wait<'a, 'b, T: Send>(lock: &'a Mutex<State<T>>,
-                         mut guard: MutexGuard<'b, State<T>>,
-                         f: fn(SignalToken) -> Blocker)
-                         -> MutexGuard<'a, State<T>>
-{
-    let (wait_token, signal_token) = blocking::tokens();
-    match mem::replace(&mut guard.blocker, f(signal_token)) {
-        NoneBlocked => {}
-        _ => unreachable!(),
-    }
-    drop(guard);        // unlock
-    wait_token.wait();  // block
-    lock.lock()         // relock
-}
-
-/// Wakes up a thread, dropping the lock at the correct time
-fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) {
-    // We need to be careful to wake up the waiting task *outside* of the mutex
-    // in case it incurs a context switch.
-    drop(guard);
-    token.signal();
-}
-
-impl<T: Send> Packet<T> {
-    pub fn new(cap: uint) -> Packet<T> {
-        Packet {
-            channels: atomic::AtomicUint::new(1),
-            lock: Mutex::new(State {
-                disconnected: false,
-                blocker: NoneBlocked,
-                cap: cap,
-                canceled: None,
-                queue: Queue {
-                    head: 0 as *mut Node,
-                    tail: 0 as *mut Node,
-                },
-                buf: Buffer {
-                    buf: Vec::from_fn(cap + if cap == 0 {1} else {0}, |_| None),
-                    start: 0,
-                    size: 0,
-                },
-            }),
-        }
-    }
-
-    // wait until a send slot is available, returning locked access to
-    // the channel state.
-    fn acquire_send_slot(&self) -> MutexGuard<State<T>> {
-        let mut node = Node { token: None, next: 0 as *mut Node };
-        loop {
-            let mut guard = self.lock.lock();
-            // are we ready to go?
-            if guard.disconnected || guard.buf.size() < guard.buf.cap() {
-                return guard;
-            }
-            // no room; actually block
-            let wait_token = guard.queue.enqueue(&mut node);
-            drop(guard);
-            wait_token.wait();
-        }
-    }
-
-    pub fn send(&self, t: T) -> Result<(), T> {
-        let mut guard = self.acquire_send_slot();
-        if guard.disconnected { return Err(t) }
-        guard.buf.enqueue(t);
-
-        match mem::replace(&mut guard.blocker, NoneBlocked) {
-            // if our capacity is 0, then we need to wait for a receiver to be
-            // available to take our data. After waiting, we check again to make
-            // sure the port didn't go away in the meantime. If it did, we need
-            // to hand back our data.
-            NoneBlocked if guard.cap == 0 => {
-                let mut canceled = false;
-                assert!(guard.canceled.is_none());
-                guard.canceled = Some(unsafe { mem::transmute(&mut canceled) });
-                let mut guard = wait(&self.lock, guard, BlockedSender);
-                if canceled {Err(guard.buf.dequeue())} else {Ok(())}
-            }
-
-            // success, we buffered some data
-            NoneBlocked => Ok(()),
-
-            // success, someone's about to receive our buffered data.
-            BlockedReceiver(token) => { wakeup(token, guard); Ok(()) }
-
-            BlockedSender(..) => panic!("lolwut"),
-        }
-    }
-
-    pub fn try_send(&self, t: T) -> Result<(), super::TrySendError<T>> {
-        let mut guard = self.lock.lock();
-        if guard.disconnected {
-            Err(super::RecvDisconnected(t))
-        } else if guard.buf.size() == guard.buf.cap() {
-            Err(super::Full(t))
-        } else if guard.cap == 0 {
-            // With capacity 0, even though we have buffer space we can't
-            // transfer the data unless there's a receiver waiting.
-            match mem::replace(&mut guard.blocker, NoneBlocked) {
-                NoneBlocked => Err(super::Full(t)),
-                BlockedSender(..) => unreachable!(),
-                BlockedReceiver(token) => {
-                    guard.buf.enqueue(t);
-                    wakeup(token, guard);
-                    Ok(())
-                }
-            }
-        } else {
-            // 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());
-            guard.buf.enqueue(t);
-            match mem::replace(&mut guard.blocker, NoneBlocked) {
-                BlockedReceiver(token) => wakeup(token, guard),
-                NoneBlocked => {}
-                BlockedSender(..) => unreachable!(),
-            }
-            Ok(())
-        }
-    }
-
-    // Receives a message from this channel
-    //
-    // When reading this, remember that there can only ever be one receiver at
-    // time.
-    pub fn recv(&self) -> Result<T, ()> {
-        let mut guard = self.lock.lock();
-
-        // Wait for the buffer to have something in it. No need for a while loop
-        // because we're the only receiver.
-        let mut waited = false;
-        if !guard.disconnected && guard.buf.size() == 0 {
-            guard = wait(&self.lock, guard, BlockedReceiver);
-            waited = true;
-        }
-        if guard.disconnected && guard.buf.size() == 0 { return Err(()) }
-
-        // Pick up the data, wake up our neighbors, and carry on
-        assert!(guard.buf.size() > 0);
-        let ret = guard.buf.dequeue();
-        self.wakeup_senders(waited, guard);
-        return Ok(ret);
-    }
-
-    pub fn try_recv(&self) -> Result<T, Failure> {
-        let mut guard = self.lock.lock();
-
-        // Easy cases first
-        if guard.disconnected { return Err(Disconnected) }
-        if guard.buf.size() == 0 { return Err(Empty) }
-
-        // Be sure to wake up neighbors
-        let ret = Ok(guard.buf.dequeue());
-        self.wakeup_senders(false, guard);
-
-        return ret;
-    }
-
-    // Wake up pending senders after some data has been received
-    //
-    // * `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>>) {
-        let pending_sender1: Option<SignalToken> = guard.queue.dequeue();
-
-        // If this is a no-buffer channel (cap == 0), then if we didn't wait we
-        // need to ACK the sender. If we waited, then the sender waking us up
-        // was already the ACK.
-        let pending_sender2 = if guard.cap == 0 && !waited {
-            match mem::replace(&mut guard.blocker, NoneBlocked) {
-                NoneBlocked => None,
-                BlockedReceiver(..) => unreachable!(),
-                BlockedSender(token) => {
-                    guard.canceled.take();
-                    Some(token)
-                }
-            }
-        } else {
-            None
-        };
-        mem::drop(guard);
-
-        // only outside of the lock do we wake up the pending tasks
-        pending_sender1.map(|t| t.signal());
-        pending_sender2.map(|t| t.signal());
-    }
-
-    // Prepares this shared packet for a channel clone, essentially just bumping
-    // a refcount.
-    pub fn clone_chan(&self) {
-        self.channels.fetch_add(1, atomic::SeqCst);
-    }
-
-    pub fn drop_chan(&self) {
-        // Only flag the channel as disconnected if we're the last channel
-        match self.channels.fetch_sub(1, atomic::SeqCst) {
-            1 => {}
-            _ => return
-        }
-
-        // Not much to do other than wake up a receiver if one's there
-        let mut guard = self.lock.lock();
-        if guard.disconnected { return }
-        guard.disconnected = true;
-        match mem::replace(&mut guard.blocker, NoneBlocked) {
-            NoneBlocked => {}
-            BlockedSender(..) => unreachable!(),
-            BlockedReceiver(token) => wakeup(token, guard),
-        }
-    }
-
-    pub fn drop_port(&self) {
-        let mut guard = self.lock.lock();
-
-        if guard.disconnected { return }
-        guard.disconnected = true;
-
-        // If the capacity is 0, then the sender may want its data back after
-        // we're disconnected. Otherwise it's now our responsibility to destroy
-        // the buffered data. As with many other portions of this code, this
-        // 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())
-        } else {
-            Vec::new()
-        };
-        let mut queue = mem::replace(&mut guard.queue, Queue {
-            head: 0 as *mut Node,
-            tail: 0 as *mut Node,
-        });
-
-        let waiter = match mem::replace(&mut guard.blocker, NoneBlocked) {
-            NoneBlocked => None,
-            BlockedSender(token) => {
-                *guard.canceled.take().unwrap() = true;
-                Some(token)
-            }
-            BlockedReceiver(..) => unreachable!(),
-        };
-        mem::drop(guard);
-
-        loop {
-            match queue.dequeue() {
-                Some(token) => { token.signal(); }
-                None => break,
-            }
-        }
-        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();
-        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();
-        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 task from this port. This ensures that the
-    // blocked task 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();
-        match mem::replace(&mut guard.blocker, NoneBlocked) {
-            NoneBlocked => true,
-            BlockedSender(token) => {
-                guard.blocker = BlockedSender(token);
-                true
-            }
-            BlockedReceiver(token) => { drop(token); false }
-        }
-    }
-}
-
-#[unsafe_destructor]
-impl<T: Send> Drop for Packet<T> {
-    fn drop(&mut self) {
-        assert_eq!(self.channels.load(atomic::SeqCst), 0);
-        let mut guard = self.lock.lock();
-        assert!(guard.queue.dequeue().is_none());
-        assert!(guard.canceled.is_none());
-    }
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// Buffer, a simple ring buffer backed by Vec<T>
-////////////////////////////////////////////////////////////////////////////////
-
-impl<T> Buffer<T> {
-    fn enqueue(&mut self, t: T) {
-        let pos = (self.start + self.size) % self.buf.len();
-        self.size += 1;
-        let prev = mem::replace(&mut self.buf[pos], Some(t));
-        assert!(prev.is_none());
-    }
-
-    fn dequeue(&mut self) -> T {
-        let start = self.start;
-        self.size -= 1;
-        self.start = (self.start + 1) % self.buf.len();
-        self.buf[start].take().unwrap()
-    }
-
-    fn size(&self) -> uint { self.size }
-    fn cap(&self) -> uint { self.buf.len() }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Queue, a simple queue to enqueue tasks with (stack-allocated nodes)
-////////////////////////////////////////////////////////////////////////////////
-
-impl Queue {
-    fn enqueue(&mut self, node: &mut Node) -> WaitToken {
-        let (wait_token, signal_token) = blocking::tokens();
-        node.token = Some(signal_token);
-        node.next = 0 as *mut Node;
-
-        if self.tail.is_null() {
-            self.head = node as *mut Node;
-            self.tail = node as *mut Node;
-        } else {
-            unsafe {
-                (*self.tail).next = node as *mut Node;
-                self.tail = node as *mut Node;
-            }
-        }
-
-        wait_token
-    }
-
-    fn dequeue(&mut self) -> Option<SignalToken> {
-        if self.head.is_null() {
-            return None
-        }
-        let node = self.head;
-        self.head = unsafe { (*node).next };
-        if self.head.is_null() {
-            self.tail = 0 as *mut Node;
-        }
-        unsafe {
-            (*node).next = 0 as *mut Node;
-            Some((*node).token.take().unwrap())
-        }
-    }
-}
index 7bf459152737840eec767759ae67e880f9684008..1679d2e552f22b8bcb02bc4b6459e12f90021917 100644 (file)
@@ -533,7 +533,7 @@ fn test_buffered_writer_inner_flushes() {
         w.write(&[0, 1]).unwrap();
         let a: &[_] = &[];
         assert_eq!(a, w.get_ref()[]);
-        let w = w.unwrap();
+        let w = w.into_inner();
         let a: &[_] = &[0, 1];
         assert_eq!(a, w[]);
     }
index be1dc0e9c34526f31339db87efb656ca77c699d2..7b8513ce423b22f985e7fbb127271fc45be122c2 100644 (file)
@@ -10,7 +10,7 @@
 
 use clone::Clone;
 use cmp;
-use comm::{Sender, Receiver};
+use sync::mpsc::{Sender, Receiver};
 use io;
 use option::Option::{None, Some};
 use result::Result::{Ok, Err};
@@ -23,7 +23,7 @@
 /// # Example
 ///
 /// ```
-/// use std::comm::channel;
+/// use std::sync::mpsc::channel;
 /// use std::io::ChanReader;
 ///
 /// let (tx, rx) = channel();
@@ -59,11 +59,11 @@ impl Buffer for ChanReader {
     fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> {
         if self.pos >= self.buf.len() {
             self.pos = 0;
-            match self.rx.recv_opt() {
+            match self.rx.recv() {
                 Ok(bytes) => {
                     self.buf = bytes;
                 },
-                Err(()) => {
+                Err(..) => {
                     self.closed = true;
                     self.buf = Vec::new();
                 }
@@ -115,7 +115,7 @@ fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
 ///
 /// ```
 /// # #![allow(unused_must_use)]
-/// use std::comm::channel;
+/// use std::sync::mpsc::channel;
 /// use std::io::ChanWriter;
 ///
 /// let (tx, rx) = channel();
@@ -143,7 +143,7 @@ fn clone(&self) -> ChanWriter {
 
 impl Writer for ChanWriter {
     fn write(&mut self, buf: &[u8]) -> IoResult<()> {
-        self.tx.send_opt(buf.to_vec()).map_err(|_| {
+        self.tx.send(buf.to_vec()).map_err(|_| {
             io::IoError {
                 kind: io::BrokenPipe,
                 desc: "Pipe closed",
@@ -158,7 +158,7 @@ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
 mod test {
     use prelude::v1::*;
 
-    use comm::channel;
+    use sync::mpsc::channel;
     use super::*;
     use io;
     use thread::Thread;
@@ -167,11 +167,11 @@ mod test {
     fn test_rx_reader() {
         let (tx, rx) = channel();
         Thread::spawn(move|| {
-          tx.send(vec![1u8, 2u8]);
-          tx.send(vec![]);
-          tx.send(vec![3u8, 4u8]);
-          tx.send(vec![5u8, 6u8]);
-          tx.send(vec![7u8, 8u8]);
+          tx.send(vec![1u8, 2u8]).unwrap();
+          tx.send(vec![]).unwrap();
+          tx.send(vec![3u8, 4u8]).unwrap();
+          tx.send(vec![5u8, 6u8]).unwrap();
+          tx.send(vec![7u8, 8u8]).unwrap();
         }).detach();
 
         let mut reader = ChanReader::new(rx);
@@ -209,12 +209,12 @@ fn test_rx_reader() {
     fn test_rx_buffer() {
         let (tx, rx) = channel();
         Thread::spawn(move|| {
-          tx.send(b"he".to_vec());
-          tx.send(b"llo wo".to_vec());
-          tx.send(b"".to_vec());
-          tx.send(b"rld\nhow ".to_vec());
-          tx.send(b"are you?".to_vec());
-          tx.send(b"".to_vec());
+          tx.send(b"he".to_vec()).unwrap();
+          tx.send(b"llo wo".to_vec()).unwrap();
+          tx.send(b"".to_vec()).unwrap();
+          tx.send(b"rld\nhow ".to_vec()).unwrap();
+          tx.send(b"are you?".to_vec()).unwrap();
+          tx.send(b"".to_vec()).unwrap();
         }).detach();
 
         let mut reader = ChanReader::new(rx);
@@ -234,7 +234,7 @@ fn test_chan_writer() {
         writer.write_be_u32(42).unwrap();
 
         let wanted = vec![0u8, 0u8, 0u8, 42u8];
-        let got = match Thread::spawn(move|| { rx.recv() }).join() {
+        let got = match Thread::spawn(move|| { rx.recv().unwrap() }).join() {
             Ok(got) => got,
             Err(_) => panic!(),
         };
index 4341666a27e52c0ff8368767f23b37e1fce17637..71c42273c22199a98b33c87e9d74b69e32632bce 100644 (file)
@@ -402,8 +402,8 @@ mod test {
     use prelude::v1::*;
 
     use super::*;
-    use io::*;
     use io;
+    use io::{SeekSet, SeekCur, SeekEnd};
     use self::test_crate::Bencher;
 
     #[test]
index f5edf8955d8b0d095e18a841c4c0b4037774638d..68f3a8e1836356bb494a575627309c125b2e2102 100644 (file)
@@ -267,11 +267,13 @@ fn as_inner(&self) -> &UnixAcceptorImp {
 mod tests {
     use prelude::v1::*;
 
-    use comm::channel;
-    use io::*;
     use io::fs::PathExtensions;
+    use io::{EndOfFile, TimedOut, ShortWrite, IoError, ConnectionReset};
+    use io::{NotConnected, BrokenPipe, FileNotFound, InvalidInput, OtherIoError};
+    use io::{PermissionDenied, Acceptor, Listener};
     use io::test::*;
     use super::*;
+    use sync::mpsc::channel;
     use thread::Thread;
     use time::Duration;
 
@@ -431,18 +433,18 @@ fn unix_clone_smoke() {
         let (tx2, rx2) = channel();
         let _t = Thread::spawn(move|| {
             let mut s2 = s2;
-            rx1.recv();
+            rx1.recv().unwrap();
             debug!("writer writing");
             s2.write(&[1]).unwrap();
             debug!("writer done");
-            tx2.send(());
+            tx2.send(()).unwrap();
         });
-        tx1.send(());
+        tx1.send(()).unwrap();
         let mut buf = [0, 0];
         debug!("reader reading");
         assert_eq!(s1.read(&mut buf), Ok(1));
         debug!("reader done");
-        rx2.recv();
+        rx2.recv().unwrap();
     }
 
     #[test]
@@ -455,9 +457,9 @@ fn unix_clone_two_read() {
         let _t = Thread::spawn(move|| {
             let mut s = UnixStream::connect(&addr);
             s.write(&[1]).unwrap();
-            rx.recv();
+            rx.recv().unwrap();
             s.write(&[2]).unwrap();
-            rx.recv();
+            rx.recv().unwrap();
         });
 
         let mut s1 = acceptor.accept().unwrap();
@@ -468,14 +470,14 @@ fn unix_clone_two_read() {
             let mut s2 = s2;
             let mut buf = [0, 0];
             s2.read(&mut buf).unwrap();
-            tx2.send(());
-            done.send(());
+            tx2.send(()).unwrap();
+            done.send(()).unwrap();
         });
         let mut buf = [0, 0];
         s1.read(&mut buf).unwrap();
-        tx1.send(());
+        tx1.send(()).unwrap();
 
-        rx.recv();
+        rx.recv().unwrap();
     }
 
     #[test]
@@ -497,11 +499,11 @@ fn unix_clone_two_write() {
         let _t = Thread::spawn(move|| {
             let mut s2 = s2;
             s2.write(&[1]).unwrap();
-            tx.send(());
+            tx.send(()).unwrap();
         });
         s1.write(&[2]).unwrap();
 
-        rx.recv();
+        rx.recv().unwrap();
     }
 
     #[cfg(not(windows))]
@@ -542,9 +544,9 @@ fn accept_timeout() {
         let (tx, rx) = channel();
         let addr2 = addr.clone();
         let _t = Thread::spawn(move|| {
-            tx.send(UnixStream::connect(&addr2).unwrap());
+            tx.send(UnixStream::connect(&addr2).unwrap()).unwrap();
         });
-        let l = rx.recv();
+        let l = rx.recv().unwrap();
         for i in range(0u, 1001) {
             match a.accept() {
                 Ok(..) => break,
@@ -600,7 +602,7 @@ fn close_readwrite_smoke() {
         Thread::spawn(move|| {
             let mut a = a;
             let _s = a.accept().unwrap();
-            let _ = rx.recv_opt();
+            let _ = rx.recv();
         }).detach();
 
         let mut b = [0];
@@ -637,7 +639,7 @@ fn close_read_wakes_up() {
         Thread::spawn(move|| {
             let mut a = a;
             let _s = a.accept().unwrap();
-            let _ = rx.recv_opt();
+            let _ = rx.recv();
         }).detach();
 
         let mut s = UnixStream::connect(&addr).unwrap();
@@ -646,13 +648,13 @@ fn close_read_wakes_up() {
         let _t = Thread::spawn(move|| {
             let mut s2 = s2;
             assert!(s2.read(&mut [0]).is_err());
-            tx.send(());
+            tx.send(()).unwrap();
         });
         // this should wake up the child task
         s.close_read().unwrap();
 
         // this test will never finish if the child doesn't wake up
-        rx.recv();
+        rx.recv().unwrap();
     }
 
     #[test]
@@ -662,9 +664,9 @@ fn readwrite_timeouts() {
         let (tx, rx) = channel::<()>();
         Thread::spawn(move|| {
             let mut s = UnixStream::connect(&addr).unwrap();
-            rx.recv();
+            rx.recv().unwrap();
             assert!(s.write(&[0]).is_ok());
-            let _ = rx.recv_opt();
+            let _ = rx.recv();
         }).detach();
 
         let mut s = a.accept().unwrap();
@@ -688,7 +690,7 @@ fn readwrite_timeouts() {
             assert_eq!(s.write(&[0]).err().unwrap().kind, TimedOut);
         }
 
-        tx.send(());
+        tx.send(()).unwrap();
         s.set_timeout(None);
         assert_eq!(s.read(&mut [0, 0]), Ok(1));
     }
@@ -700,7 +702,7 @@ fn read_timeouts() {
         let (tx, rx) = channel::<()>();
         Thread::spawn(move|| {
             let mut s = UnixStream::connect(&addr).unwrap();
-            rx.recv();
+            rx.recv().unwrap();
             let mut amt = 0;
             while amt < 100 * 128 * 1024 {
                 match s.read(&mut [0, ..128 * 1024]) {
@@ -708,7 +710,7 @@ fn read_timeouts() {
                     Err(e) => panic!("{}", e),
                 }
             }
-            let _ = rx.recv_opt();
+            let _ = rx.recv();
         }).detach();
 
         let mut s = a.accept().unwrap();
@@ -716,7 +718,7 @@ fn read_timeouts() {
         assert_eq!(s.read(&mut [0]).err().unwrap().kind, TimedOut);
         assert_eq!(s.read(&mut [0]).err().unwrap().kind, TimedOut);
 
-        tx.send(());
+        tx.send(()).unwrap();
         for _ in range(0u, 100) {
             assert!(s.write(&[0, ..128 * 1024]).is_ok());
         }
@@ -729,9 +731,9 @@ fn write_timeouts() {
         let (tx, rx) = channel::<()>();
         Thread::spawn(move|| {
             let mut s = UnixStream::connect(&addr).unwrap();
-            rx.recv();
+            rx.recv().unwrap();
             assert!(s.write(&[0]).is_ok());
-            let _ = rx.recv_opt();
+            let _ = rx.recv();
         }).detach();
 
         let mut s = a.accept().unwrap();
@@ -745,7 +747,7 @@ fn write_timeouts() {
            if i == 1000 { panic!("should have filled up?!"); }
         }
 
-        tx.send(());
+        tx.send(()).unwrap();
         assert!(s.read(&mut [0]).is_ok());
     }
 
@@ -756,9 +758,9 @@ fn timeout_concurrent_read() {
         let (tx, rx) = channel::<()>();
         Thread::spawn(move|| {
             let mut s = UnixStream::connect(&addr).unwrap();
-            rx.recv();
+            rx.recv().unwrap();
             assert!(s.write(&[0]).is_ok());
-            let _ = rx.recv_opt();
+            let _ = rx.recv();
         }).detach();
 
         let mut s = a.accept().unwrap();
@@ -767,14 +769,14 @@ fn timeout_concurrent_read() {
         let _t = Thread::spawn(move|| {
             let mut s2 = s2;
             assert!(s2.read(&mut [0]).is_ok());
-            tx2.send(());
+            tx2.send(()).unwrap();
         });
 
         s.set_read_timeout(Some(20));
         assert_eq!(s.read(&mut [0]).err().unwrap().kind, TimedOut);
-        tx.send(());
+        tx.send(()).unwrap();
 
-        rx2.recv();
+        rx2.recv().unwrap();
     }
 
     #[cfg(not(windows))]
@@ -809,8 +811,14 @@ fn clone_accept_concurrent() {
         let (tx, rx) = channel();
         let tx2 = tx.clone();
 
-        let _t = Thread::spawn(move|| { let mut a = a; tx.send(a.accept()) });
-        let _t = Thread::spawn(move|| { let mut a = a2; tx2.send(a.accept()) });
+        let _t = Thread::spawn(move|| {
+            let mut a = a;
+            tx.send(a.accept()).unwrap()
+        });
+        let _t = Thread::spawn(move|| {
+            let mut a = a2;
+            tx2.send(a.accept()).unwrap()
+        });
 
         let addr2 = addr.clone();
         let _t = Thread::spawn(move|| {
@@ -820,8 +828,8 @@ fn clone_accept_concurrent() {
             let _ = UnixStream::connect(&addr);
         });
 
-        assert!(rx.recv().is_ok());
-        assert!(rx.recv().is_ok());
+        assert!(rx.recv().unwrap().is_ok());
+        assert!(rx.recv().unwrap().is_ok());
     }
 
     #[test]
@@ -844,10 +852,10 @@ fn close_accept_concurrent() {
         let (tx, rx) = channel();
         let _t = Thread::spawn(move|| {
             let mut a = a;
-            tx.send(a.accept());
+            tx.send(a.accept()).unwrap();
         });
         a2.close_accept().unwrap();
 
-        assert_eq!(rx.recv().err().unwrap().kind, EndOfFile);
+        assert_eq!(rx.recv().unwrap().err().unwrap().kind, EndOfFile);
     }
 }
index 67aaf7dda8ebf6b6333001ef814f2c1aab965ac2..57ffcfaad30a786c55b5cbfc2352c54c485f098b 100644 (file)
@@ -484,12 +484,15 @@ fn as_inner(&self) -> &TcpAcceptorImp {
 mod test {
     use prelude::v1::*;
 
-    use comm::channel;
+    use sync::mpsc::channel;
     use thread::Thread;
     use io::net::tcp::*;
     use io::net::ip::*;
-    use io::*;
     use io::test::*;
+    use io::{EndOfFile, TimedOut, ShortWrite, IoError};
+    use io::{ConnectionRefused, BrokenPipe, ConnectionAborted};
+    use io::{ConnectionReset, NotConnected, PermissionDenied, OtherIoError};
+    use io::{Acceptor, Listener};
 
     // FIXME #11530 this fails on android because tests are run as root
     #[cfg_attr(any(windows, target_os = "android"), ignore)]
@@ -694,11 +697,11 @@ fn write_close_ip4() {
         let (tx, rx) = channel();
         let _t = Thread::spawn(move|| {
             drop(TcpStream::connect(addr));
-            tx.send(());
+            tx.send(()).unwrap();
         });
 
         let mut stream = acceptor.accept();
-        rx.recv();
+        rx.recv().unwrap();
         let buf = [0];
         match stream.write(&buf) {
             Ok(..) => {}
@@ -719,11 +722,11 @@ fn write_close_ip6() {
         let (tx, rx) = channel();
         let _t = Thread::spawn(move|| {
             drop(TcpStream::connect(addr));
-            tx.send(());
+            tx.send(()).unwrap();
         });
 
         let mut stream = acceptor.accept();
-        rx.recv();
+        rx.recv().unwrap();
         let buf = [0];
         match stream.write(&buf) {
             Ok(..) => {}
@@ -969,20 +972,20 @@ fn partial_read() {
         let (tx, rx) = channel();
         let _t = Thread::spawn(move|| {
             let mut srv = TcpListener::bind(addr).listen().unwrap();
-            tx.send(());
+            tx.send(()).unwrap();
             let mut cl = srv.accept().unwrap();
             cl.write(&[10]).unwrap();
             let mut b = [0];
             cl.read(&mut b).unwrap();
-            tx.send(());
+            tx.send(()).unwrap();
         });
 
-        rx.recv();
+        rx.recv().unwrap();
         let mut c = TcpStream::connect(addr).unwrap();
         let mut b = [0, ..10];
         assert_eq!(c.read(&mut b), Ok(1));
         c.write(&[1]).unwrap();
-        rx.recv();
+        rx.recv().unwrap();
     }
 
     #[test]
@@ -1005,19 +1008,19 @@ fn fast_rebind() {
         let (tx, rx) = channel();
 
         let _t = Thread::spawn(move|| {
-            rx.recv();
+            rx.recv().unwrap();
             let _stream = TcpStream::connect(addr).unwrap();
             // Close
-            rx.recv();
+            rx.recv().unwrap();
         });
 
         {
             let mut acceptor = TcpListener::bind(addr).listen();
-            tx.send(());
+            tx.send(()).unwrap();
             {
                 let _stream = acceptor.accept().unwrap();
                 // Close client
-                tx.send(());
+                tx.send(()).unwrap();
             }
             // Close listener
         }
@@ -1044,14 +1047,14 @@ fn tcp_clone_smoke() {
         let (tx2, rx2) = channel();
         let _t = Thread::spawn(move|| {
             let mut s2 = s2;
-            rx1.recv();
+            rx1.recv().unwrap();
             s2.write(&[1]).unwrap();
-            tx2.send(());
+            tx2.send(()).unwrap();
         });
-        tx1.send(());
+        tx1.send(()).unwrap();
         let mut buf = [0, 0];
         assert_eq!(s1.read(&mut buf), Ok(1));
-        rx2.recv();
+        rx2.recv().unwrap();
     }
 
     #[test]
@@ -1064,9 +1067,9 @@ fn tcp_clone_two_read() {
         let _t = Thread::spawn(move|| {
             let mut s = TcpStream::connect(addr);
             s.write(&[1]).unwrap();
-            rx.recv();
+            rx.recv().unwrap();
             s.write(&[2]).unwrap();
-            rx.recv();
+            rx.recv().unwrap();
         });
 
         let mut s1 = acceptor.accept().unwrap();
@@ -1077,14 +1080,14 @@ fn tcp_clone_two_read() {
             let mut s2 = s2;
             let mut buf = [0, 0];
             s2.read(&mut buf).unwrap();
-            tx2.send(());
-            done.send(());
+            tx2.send(()).unwrap();
+            done.send(()).unwrap();
         });
         let mut buf = [0, 0];
         s1.read(&mut buf).unwrap();
-        tx1.send(());
+        tx1.send(()).unwrap();
 
-        rx.recv();
+        rx.recv().unwrap();
     }
 
     #[test]
@@ -1106,11 +1109,11 @@ fn tcp_clone_two_write() {
         let _t = Thread::spawn(move|| {
             let mut s2 = s2;
             s2.write(&[1]).unwrap();
-            done.send(());
+            done.send(()).unwrap();
         });
         s1.write(&[2]).unwrap();
 
-        rx.recv();
+        rx.recv().unwrap();
     }
 
     #[test]
@@ -1152,9 +1155,9 @@ fn accept_timeout() {
         if !cfg!(target_os = "freebsd") {
             let (tx, rx) = channel();
             let _t = Thread::spawn(move|| {
-                tx.send(TcpStream::connect(addr).unwrap());
+                tx.send(TcpStream::connect(addr).unwrap()).unwrap();
             });
-            let _l = rx.recv();
+            let _l = rx.recv().unwrap();
             for i in range(0i, 1001) {
                 match a.accept() {
                     Ok(..) => break,
@@ -1182,7 +1185,7 @@ fn close_readwrite_smoke() {
         Thread::spawn(move|| {
             let mut a = a;
             let _s = a.accept().unwrap();
-            let _ = rx.recv_opt();
+            let _ = rx.recv().unwrap();
         }).detach();
 
         let mut b = [0];
@@ -1219,7 +1222,7 @@ fn close_read_wakes_up() {
         Thread::spawn(move|| {
             let mut a = a;
             let _s = a.accept().unwrap();
-            let _ = rx.recv_opt();
+            let _ = rx.recv().unwrap();
         }).detach();
 
         let mut s = TcpStream::connect(addr).unwrap();
@@ -1228,13 +1231,13 @@ fn close_read_wakes_up() {
         let _t = Thread::spawn(move|| {
             let mut s2 = s2;
             assert!(s2.read(&mut [0]).is_err());
-            tx.send(());
+            tx.send(()).unwrap();
         });
         // this should wake up the child task
         s.close_read().unwrap();
 
         // this test will never finish if the child doesn't wake up
-        rx.recv();
+        rx.recv().unwrap();
     }
 
     #[test]
@@ -1244,9 +1247,9 @@ fn readwrite_timeouts() {
         let (tx, rx) = channel::<()>();
         Thread::spawn(move|| {
             let mut s = TcpStream::connect(addr).unwrap();
-            rx.recv();
+            rx.recv().unwrap();
             assert!(s.write(&[0]).is_ok());
-            let _ = rx.recv_opt();
+            let _ = rx.recv();
         }).detach();
 
         let mut s = a.accept().unwrap();
@@ -1265,7 +1268,7 @@ fn readwrite_timeouts() {
         }
         assert_eq!(s.write(&[0]).err().unwrap().kind, TimedOut);
 
-        tx.send(());
+        tx.send(()).unwrap();
         s.set_timeout(None);
         assert_eq!(s.read(&mut [0, 0]), Ok(1));
     }
@@ -1277,7 +1280,7 @@ fn read_timeouts() {
         let (tx, rx) = channel::<()>();
         Thread::spawn(move|| {
             let mut s = TcpStream::connect(addr).unwrap();
-            rx.recv();
+            rx.recv().unwrap();
             let mut amt = 0;
             while amt < 100 * 128 * 1024 {
                 match s.read(&mut [0, ..128 * 1024]) {
@@ -1285,7 +1288,7 @@ fn read_timeouts() {
                     Err(e) => panic!("{}", e),
                 }
             }
-            let _ = rx.recv_opt();
+            let _ = rx.recv();
         }).detach();
 
         let mut s = a.accept().unwrap();
@@ -1293,7 +1296,7 @@ fn read_timeouts() {
         assert_eq!(s.read(&mut [0]).err().unwrap().kind, TimedOut);
         assert_eq!(s.read(&mut [0]).err().unwrap().kind, TimedOut);
 
-        tx.send(());
+        tx.send(()).unwrap();
         for _ in range(0i, 100) {
             assert!(s.write(&[0, ..128 * 1024]).is_ok());
         }
@@ -1306,9 +1309,9 @@ fn write_timeouts() {
         let (tx, rx) = channel::<()>();
         Thread::spawn(move|| {
             let mut s = TcpStream::connect(addr).unwrap();
-            rx.recv();
+            rx.recv().unwrap();
             assert!(s.write(&[0]).is_ok());
-            let _ = rx.recv_opt();
+            let _ = rx.recv();
         }).detach();
 
         let mut s = a.accept().unwrap();
@@ -1323,7 +1326,7 @@ fn write_timeouts() {
         }
         assert_eq!(s.write(&[0]).err().unwrap().kind, TimedOut);
 
-        tx.send(());
+        tx.send(()).unwrap();
         assert!(s.read(&mut [0]).is_ok());
     }
 
@@ -1334,9 +1337,9 @@ fn timeout_concurrent_read() {
         let (tx, rx) = channel::<()>();
         Thread::spawn(move|| {
             let mut s = TcpStream::connect(addr).unwrap();
-            rx.recv();
+            rx.recv().unwrap();
             assert_eq!(s.write(&[0]), Ok(()));
-            let _ = rx.recv_opt();
+            let _ = rx.recv();
         }).detach();
 
         let mut s = a.accept().unwrap();
@@ -1345,14 +1348,14 @@ fn timeout_concurrent_read() {
         let _t = Thread::spawn(move|| {
             let mut s2 = s2;
             assert_eq!(s2.read(&mut [0]), Ok(1));
-            tx2.send(());
+            tx2.send(()).unwrap();
         });
 
         s.set_read_timeout(Some(20));
         assert_eq!(s.read(&mut [0]).err().unwrap().kind, TimedOut);
-        tx.send(());
+        tx.send(()).unwrap();
 
-        rx2.recv();
+        rx2.recv().unwrap();
     }
 
     #[test]
@@ -1367,9 +1370,9 @@ fn clone_while_reading() {
         let txdone2 = txdone.clone();
         let _t = Thread::spawn(move|| {
             let mut tcp = TcpStream::connect(addr).unwrap();
-            rx.recv();
+            rx.recv().unwrap();
             tcp.write_u8(0).unwrap();
-            txdone2.send(());
+            txdone2.send(()).unwrap();
         });
 
         // Spawn off a reading clone
@@ -1379,7 +1382,7 @@ fn clone_while_reading() {
         let _t = Thread::spawn(move|| {
             let mut tcp2 = tcp2;
             tcp2.read_u8().unwrap();
-            txdone3.send(());
+            txdone3.send(()).unwrap();
         });
 
         // Try to ensure that the reading clone is indeed reading
@@ -1390,9 +1393,9 @@ fn clone_while_reading() {
         // clone the handle again while it's reading, then let it finish the
         // read.
         let _ = tcp.clone();
-        tx.send(());
-        rxdone.recv();
-        rxdone.recv();
+        tx.send(()).unwrap();
+        rxdone.recv().unwrap();
+        rxdone.recv().unwrap();
     }
 
     #[test]
@@ -1423,8 +1426,14 @@ fn clone_accept_concurrent() {
         let (tx, rx) = channel();
         let tx2 = tx.clone();
 
-        let _t = Thread::spawn(move|| { let mut a = a; tx.send(a.accept()) });
-        let _t = Thread::spawn(move|| { let mut a = a2; tx2.send(a.accept()) });
+        let _t = Thread::spawn(move|| {
+            let mut a = a;
+            tx.send(a.accept()).unwrap();
+        });
+        let _t = Thread::spawn(move|| {
+            let mut a = a2;
+            tx2.send(a.accept()).unwrap();
+        });
 
         let _t = Thread::spawn(move|| {
             let _ = TcpStream::connect(addr);
@@ -1433,8 +1442,8 @@ fn clone_accept_concurrent() {
             let _ = TcpStream::connect(addr);
         });
 
-        assert!(rx.recv().is_ok());
-        assert!(rx.recv().is_ok());
+        assert!(rx.recv().unwrap().is_ok());
+        assert!(rx.recv().unwrap().is_ok());
     }
 
     #[test]
@@ -1457,10 +1466,10 @@ fn close_accept_concurrent() {
         let (tx, rx) = channel();
         let _t = Thread::spawn(move|| {
             let mut a = a;
-            tx.send(a.accept());
+            tx.send(a.accept()).unwrap();
         });
         a2.close_accept().unwrap();
 
-        assert_eq!(rx.recv().err().unwrap().kind, EndOfFile);
+        assert_eq!(rx.recv().unwrap().err().unwrap().kind, EndOfFile);
     }
 }
index 84269eb1ed9cdeb6d392445cdb3c33092bf03c89..d6c379cc9f7609f0f8b2b49e5a659abcb6edbe43 100644 (file)
@@ -250,10 +250,10 @@ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
 mod test {
     use prelude::v1::*;
 
-    use comm::channel;
-    use io::*;
+    use sync::mpsc::channel;
     use io::net::ip::*;
     use io::test::*;
+    use io::{IoError, TimedOut, PermissionDenied, ShortWrite};
     use super::*;
     use thread::Thread;
 
@@ -278,17 +278,17 @@ fn socket_smoke_test_ip4() {
         let _t = Thread::spawn(move|| {
             match UdpSocket::bind(client_ip) {
                 Ok(ref mut client) => {
-                    rx1.recv();
+                    rx1.recv().unwrap();
                     client.send_to(&[99], server_ip).unwrap()
                 }
                 Err(..) => panic!()
             }
-            tx2.send(());
+            tx2.send(()).unwrap();
         });
 
         match UdpSocket::bind(server_ip) {
             Ok(ref mut server) => {
-                tx1.send(());
+                tx1.send(()).unwrap();
                 let mut buf = [0];
                 match server.recv_from(&mut buf) {
                     Ok((nread, src)) => {
@@ -301,7 +301,7 @@ fn socket_smoke_test_ip4() {
             }
             Err(..) => panic!()
         }
-        rx2.recv();
+        rx2.recv().unwrap();
     }
 
     #[test]
@@ -313,7 +313,7 @@ fn socket_smoke_test_ip6() {
         let _t = Thread::spawn(move|| {
             match UdpSocket::bind(client_ip) {
                 Ok(ref mut client) => {
-                    rx.recv();
+                    rx.recv().unwrap();
                     client.send_to(&[99], server_ip).unwrap()
                 }
                 Err(..) => panic!()
@@ -322,7 +322,7 @@ fn socket_smoke_test_ip6() {
 
         match UdpSocket::bind(server_ip) {
             Ok(ref mut server) => {
-                tx.send(());
+                tx.send(()).unwrap();
                 let mut buf = [0];
                 match server.recv_from(&mut buf) {
                     Ok((nread, src)) => {
@@ -357,17 +357,17 @@ fn stream_smoke_test_ip4() {
                     Err(..) => panic!()
                 }
             };
-            rx1.recv();
+            rx1.recv().unwrap();
             send_as(dummy_ip, &[98]);
             send_as(client_ip, &[99]);
-            tx2.send(());
+            tx2.send(()).unwrap();
         });
 
         match UdpSocket::bind(server_ip) {
             Ok(server) => {
                 let server = box server;
                 let mut stream = server.connect(client_ip);
-                tx1.send(());
+                tx1.send(()).unwrap();
                 let mut buf = [0];
                 match stream.read(&mut buf) {
                     Ok(nread) => {
@@ -379,7 +379,7 @@ fn stream_smoke_test_ip4() {
             }
             Err(..) => panic!()
         }
-        rx2.recv();
+        rx2.recv().unwrap();
     }
 
     #[test]
@@ -395,19 +395,19 @@ fn stream_smoke_test_ip6() {
                 Ok(client) => {
                     let client = box client;
                     let mut stream = client.connect(server_ip);
-                    rx1.recv();
+                    rx1.recv().unwrap();
                     stream.write(&[99]).unwrap();
                 }
                 Err(..) => panic!()
             }
-            tx2.send(());
+            tx2.send(()).unwrap();
         });
 
         match UdpSocket::bind(server_ip) {
             Ok(server) => {
                 let server = box server;
                 let mut stream = server.connect(client_ip);
-                tx1.send(());
+                tx1.send(()).unwrap();
                 let mut buf = [0];
                 match stream.read(&mut buf) {
                     Ok(nread) => {
@@ -419,7 +419,7 @@ fn stream_smoke_test_ip6() {
             }
             Err(..) => panic!()
         }
-        rx2.recv();
+        rx2.recv().unwrap();
     }
 
     pub fn socket_name(addr: SocketAddr) {
@@ -466,14 +466,14 @@ fn udp_clone_smoke() {
         let (tx2, rx2) = channel();
         let _t = Thread::spawn(move|| {
             let mut sock3 = sock3;
-            rx1.recv();
+            rx1.recv().unwrap();
             sock3.send_to(&[1], addr2).unwrap();
-            tx2.send(());
+            tx2.send(()).unwrap();
         });
-        tx1.send(());
+        tx1.send(()).unwrap();
         let mut buf = [0, 0];
         assert_eq!(sock1.recv_from(&mut buf), Ok((1, addr2)));
-        rx2.recv();
+        rx2.recv().unwrap();
     }
 
     #[test]
@@ -488,9 +488,9 @@ fn udp_clone_two_read() {
         let _t = Thread::spawn(move|| {
             let mut sock2 = sock2;
             sock2.send_to(&[1], addr1).unwrap();
-            rx.recv();
+            rx.recv().unwrap();
             sock2.send_to(&[2], addr1).unwrap();
-            rx.recv();
+            rx.recv().unwrap();
         });
 
         let sock3 = sock1.clone();
@@ -500,14 +500,14 @@ fn udp_clone_two_read() {
             let mut sock3 = sock3;
             let mut buf = [0, 0];
             sock3.recv_from(&mut buf).unwrap();
-            tx2.send(());
-            done.send(());
+            tx2.send(()).unwrap();
+            done.send(()).unwrap();
         });
         let mut buf = [0, 0];
         sock1.recv_from(&mut buf).unwrap();
-        tx1.send(());
+        tx1.send(()).unwrap();
 
-        rx.recv();
+        rx.recv().unwrap();
     }
 
     #[test]
@@ -524,12 +524,12 @@ fn udp_clone_two_write() {
             let mut sock2 = sock2;
             let mut buf = [0, 1];
 
-            rx.recv();
+            rx.recv().unwrap();
             match sock2.recv_from(&mut buf) {
                 Ok(..) => {}
                 Err(e) => panic!("failed receive: {}", e),
             }
-            serv_tx.send(());
+            serv_tx.send(()).unwrap();
         });
 
         let sock3 = sock1.clone();
@@ -539,19 +539,19 @@ fn udp_clone_two_write() {
         let _t = Thread::spawn(move|| {
             let mut sock3 = sock3;
             match sock3.send_to(&[1], addr2) {
-                Ok(..) => { let _ = tx2.send_opt(()); }
+                Ok(..) => { let _ = tx2.send(()); }
                 Err(..) => {}
             }
-            done.send(());
+            done.send(()).unwrap();
         });
         match sock1.send_to(&[2], addr2) {
-            Ok(..) => { let _ = tx.send_opt(()); }
+            Ok(..) => { let _ = tx.send(()); }
             Err(..) => {}
         }
         drop(tx);
 
-        rx.recv();
-        serv_rx.recv();
+        rx.recv().unwrap();
+        serv_rx.recv().unwrap();
     }
 
     #[cfg(not(windows))] // FIXME #17553
@@ -568,10 +568,10 @@ fn recv_from_timeout() {
             let mut a = a2;
             assert_eq!(a.recv_from(&mut [0]), Ok((1, addr1)));
             assert_eq!(a.send_to(&[0], addr1), Ok(()));
-            rx.recv();
+            rx.recv().unwrap();
             assert_eq!(a.send_to(&[0], addr1), Ok(()));
 
-            tx2.send(());
+            tx2.send(()).unwrap();
         });
 
         // Make sure that reads time out, but writes can continue
@@ -586,11 +586,11 @@ fn recv_from_timeout() {
 
         // Clearing the timeout should allow for receiving
         a.set_timeout(None);
-        tx.send(());
+        tx.send(()).unwrap();
         assert_eq!(a2.recv_from(&mut [0]), Ok((1, addr2)));
 
         // Make sure the child didn't die
-        rx2.recv();
+        rx2.recv().unwrap();
     }
 
     #[test]
index 40ae49228231579628aa7f90fb7a287986aa7e94..ee3766582838a0dcefa165f15b94d663bf956dc9 100644 (file)
@@ -114,7 +114,7 @@ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
 mod test {
     use prelude::v1::*;
 
-    use comm::channel;
+    use sync::mpsc::channel;
     use thread::Thread;
 
     #[test]
@@ -129,11 +129,11 @@ fn partial_read() {
         let _t = Thread::spawn(move|| {
             let mut out = out;
             out.write(&[10]).unwrap();
-            rx.recv(); // don't close the pipe until the other read has finished
+            rx.recv().unwrap(); // don't close the pipe until the other read has finished
         });
 
         let mut buf = [0, ..10];
         input.read(&mut buf).unwrap();
-        tx.send(());
+        tx.send(()).unwrap();
     }
 }
index d1e9e2c4ea1f81b72122a05bb17c251b8e90972d..1e008287a3167af4b5604c683f429514354897b5 100644 (file)
@@ -20,7 +20,6 @@
 
 use c_str::{CString, ToCStr};
 use collections::HashMap;
-use comm::{channel, Receiver};
 use fmt;
 use hash::Hash;
 use io::pipe::{PipeStream, PipePair};
@@ -29,6 +28,7 @@
 use libc;
 use os;
 use path::BytesContainer;
+use sync::mpsc::{channel, Receiver};
 use sys::fs::FileDesc;
 use sys::process::Process as ProcessImp;
 use sys;
@@ -693,10 +693,10 @@ fn read(stream: Option<io::PipeStream>) -> Receiver<IoResult<Vec<u8>>> {
                 Some(stream) => {
                     Thread::spawn(move |:| {
                         let mut stream = stream;
-                        tx.send(stream.read_to_end())
+                        tx.send(stream.read_to_end()).unwrap();
                     }).detach();
                 }
-                None => tx.send(Ok(Vec::new()))
+                None => tx.send(Ok(Vec::new())).unwrap()
             }
             rx
         }
@@ -707,8 +707,8 @@ fn read(stream: Option<io::PipeStream>) -> Receiver<IoResult<Vec<u8>>> {
 
         Ok(ProcessOutput {
             status: status,
-            output: stdout.recv().ok().unwrap_or(Vec::new()),
-            error:  stderr.recv().ok().unwrap_or(Vec::new()),
+            output: stdout.recv().unwrap().unwrap_or(Vec::new()),
+            error:  stderr.recv().unwrap().unwrap_or(Vec::new()),
         })
     }
 
@@ -743,13 +743,15 @@ fn drop(&mut self) {
 mod tests {
     use prelude::v1::*;
 
-    use comm::channel;
-    use io::*;
     use io::fs::PathExtensions;
+    use io::process;
     use io::timer::*;
+    use io::{Truncate, Write, TimedOut, timer, FileNotFound};
     use rt::running_on_valgrind;
     use str;
-    use super::*;
+    use super::{CreatePipe};
+    use super::{InheritFd, Process, PleaseExitSignal, Command, ProcessOutput};
+    use sync::mpsc::channel;
     use thread::Thread;
     use time::Duration;
 
@@ -1160,17 +1162,17 @@ fn wait_timeout2() {
             p.set_timeout(Some(10));
             assert_eq!(p.wait().err().unwrap().kind, TimedOut);
             p.signal_kill().unwrap();
-            tx.send(());
+            tx.send(()).unwrap();
         });
         let _t = Thread::spawn(move|| {
             let mut p = sleeper();
             p.set_timeout(Some(10));
             assert_eq!(p.wait().err().unwrap().kind, TimedOut);
             p.signal_kill().unwrap();
-            tx2.send(());
+            tx2.send(()).unwrap();
         });
-        rx.recv();
-        rx.recv();
+        rx.recv().unwrap();
+        rx.recv().unwrap();
     }
 
     #[test]
index c378b95ff33d2c588d1a428ccb0e11e8f45ec887..74b0930a1450040e0fb74af1e563bf09bdde5aad 100644 (file)
@@ -543,7 +543,7 @@ mod tests {
     use prelude::v1::*;
 
     use super::*;
-    use comm::channel;
+    use sync::mpsc::channel;
     use thread::Thread;
 
     #[test]
index 2067a97fdacf906f35725ee5bad0256899ea7c16..e073f76af825ce77628696d262a99af136589f6b 100644 (file)
@@ -15,7 +15,7 @@
 
 // FIXME: These functions take Durations but only pass ms to the backend impls.
 
-use comm::{Receiver, Sender, channel};
+use sync::mpsc::{Receiver, Sender, channel};
 use time::Duration;
 use io::IoResult;
 use sys::timer::Callback;
 ///
 /// let timeout = timer.oneshot(Duration::milliseconds(10));
 /// // do some work
-/// timeout.recv(); // wait for the timeout to expire
+/// timeout.recv().unwrap(); // wait for the timeout to expire
 ///
 /// let periodic = timer.periodic(Duration::milliseconds(10));
 /// loop {
-///     periodic.recv();
+///     periodic.recv().unwrap();
 ///     // this loop is only executed once every 10ms
 /// }
 /// # }
@@ -126,7 +126,7 @@ pub fn sleep(&mut self, duration: Duration) {
     /// for _ in range(0u, 100) { /* do work */ }
     ///
     /// // blocks until 10 ms after the `oneshot` call
-    /// ten_milliseconds.recv();
+    /// ten_milliseconds.recv().unwrap();
     /// ```
     ///
     /// ```rust
@@ -136,7 +136,7 @@ pub fn sleep(&mut self, duration: Duration) {
     /// // Incorrect, method chaining-style:
     /// let mut five_ms = Timer::new().unwrap().oneshot(Duration::milliseconds(5));
     /// // The timer object was destroyed, so this will always fail:
-    /// // five_ms.recv()
+    /// // five_ms.recv().unwrap()
     /// ```
     ///
     /// When provided a zero or negative `duration`, the message will
@@ -147,7 +147,7 @@ pub fn oneshot(&mut self, duration: Duration) -> Receiver<()> {
         if in_ms_u64(duration) != 0 {
             self.inner.oneshot(in_ms_u64(duration), box TimerCallback { tx: tx });
         } else {
-            tx.send(());
+            tx.send(()).unwrap();
         }
         return rx
     }
@@ -178,13 +178,13 @@ pub fn oneshot(&mut self, duration: Duration) -> Receiver<()> {
     /// for _ in range(0u, 100) { /* do work */ }
     ///
     /// // blocks until 10 ms after the `periodic` call
-    /// ten_milliseconds.recv();
+    /// ten_milliseconds.recv().unwrap();
     ///
     /// for _ in range(0u, 100) { /* do work */ }
     ///
     /// // blocks until 20 ms after the `periodic` call (*not* 10ms after the
     /// // previous `recv`)
-    /// ten_milliseconds.recv();
+    /// ten_milliseconds.recv().unwrap();
     /// ```
     ///
     /// ```rust
@@ -194,7 +194,7 @@ pub fn oneshot(&mut self, duration: Duration) -> Receiver<()> {
     /// // Incorrect, method chaining-style.
     /// let mut five_ms = Timer::new().unwrap().periodic(Duration::milliseconds(5));
     /// // The timer object was destroyed, so this will always fail:
-    /// // five_ms.recv()
+    /// // five_ms.recv().unwrap()
     /// ```
     ///
     /// When provided a zero or negative `duration`, the messages will
@@ -213,7 +213,7 @@ pub fn periodic(&mut self, duration: Duration) -> Receiver<()> {
 
 impl Callback for TimerCallback {
     fn call(&mut self) {
-        let _ = self.tx.send_opt(());
+        let _ = self.tx.send(());
     }
 }
 
@@ -225,8 +225,6 @@ fn in_ms_u64(d: Duration) -> u64 {
 
 #[cfg(test)]
 mod test {
-    use prelude::v1::*;
-
     use super::Timer;
     use thread::Thread;
     use time::Duration;
@@ -240,7 +238,7 @@ fn test_io_timer_sleep_simple() {
     #[test]
     fn test_io_timer_sleep_oneshot() {
         let mut timer = Timer::new().unwrap();
-        timer.oneshot(Duration::milliseconds(1)).recv();
+        timer.oneshot(Duration::milliseconds(1)).recv().unwrap();
     }
 
     #[test]
@@ -254,8 +252,8 @@ fn oneshot_twice() {
         let mut timer = Timer::new().unwrap();
         let rx1 = timer.oneshot(Duration::milliseconds(10000));
         let rx = timer.oneshot(Duration::milliseconds(1));
-        rx.recv();
-        assert_eq!(rx1.recv_opt(), Err(()));
+        rx.recv().unwrap();
+        assert!(rx1.recv().is_err());
     }
 
     #[test]
@@ -264,16 +262,16 @@ fn test_io_timer_oneshot_then_sleep() {
         let rx = timer.oneshot(Duration::milliseconds(100000000));
         timer.sleep(Duration::milliseconds(1)); // this should invalidate rx
 
-        assert_eq!(rx.recv_opt(), Err(()));
+        assert!(rx.recv().is_err());
     }
 
     #[test]
     fn test_io_timer_sleep_periodic() {
         let mut timer = Timer::new().unwrap();
         let rx = timer.periodic(Duration::milliseconds(1));
-        rx.recv();
-        rx.recv();
-        rx.recv();
+        rx.recv().unwrap();
+        rx.recv().unwrap();
+        rx.recv().unwrap();
     }
 
     #[test]
@@ -292,12 +290,12 @@ fn oneshot() {
         let mut timer = Timer::new().unwrap();
 
         let rx = timer.oneshot(Duration::milliseconds(1));
-        rx.recv();
-        assert!(rx.recv_opt().is_err());
+        rx.recv().unwrap();
+        assert!(rx.recv().is_err());
 
         let rx = timer.oneshot(Duration::milliseconds(1));
-        rx.recv();
-        assert!(rx.recv_opt().is_err());
+        rx.recv().unwrap();
+        assert!(rx.recv().is_err());
     }
 
     #[test]
@@ -306,20 +304,20 @@ fn test_override() {
         let orx = timer.oneshot(Duration::milliseconds(100));
         let prx = timer.periodic(Duration::milliseconds(100));
         timer.sleep(Duration::milliseconds(1));
-        assert_eq!(orx.recv_opt(), Err(()));
-        assert_eq!(prx.recv_opt(), Err(()));
-        timer.oneshot(Duration::milliseconds(1)).recv();
+        assert!(orx.recv().is_err());
+        assert!(prx.recv().is_err());
+        timer.oneshot(Duration::milliseconds(1)).recv().unwrap();
     }
 
     #[test]
     fn period() {
         let mut timer = Timer::new().unwrap();
         let rx = timer.periodic(Duration::milliseconds(1));
-        rx.recv();
-        rx.recv();
+        rx.recv().unwrap();
+        rx.recv().unwrap();
         let rx2 = timer.periodic(Duration::milliseconds(1));
-        rx2.recv();
-        rx2.recv();
+        rx2.recv().unwrap();
+        rx2.recv().unwrap();
     }
 
     #[test]
@@ -359,7 +357,7 @@ fn closing_channel_during_drop_doesnt_kill_everything() {
         let timer_rx = timer.periodic(Duration::milliseconds(1000));
 
         Thread::spawn(move|| {
-            let _ = timer_rx.recv_opt();
+            let _ = timer_rx.recv();
         }).detach();
 
         // when we drop the TimerWatcher we're going to destroy the channel,
@@ -373,7 +371,7 @@ fn reset_doesnt_switch_tasks() {
         let timer_rx = timer.periodic(Duration::milliseconds(1000));
 
         Thread::spawn(move|| {
-            let _ = timer_rx.recv_opt();
+            let _ = timer_rx.recv();
         }).detach();
 
         timer.oneshot(Duration::milliseconds(1));
@@ -386,7 +384,7 @@ fn reset_doesnt_switch_tasks2() {
         let timer_rx = timer.periodic(Duration::milliseconds(1000));
 
         Thread::spawn(move|| {
-            let _ = timer_rx.recv_opt();
+            let _ = timer_rx.recv();
         }).detach();
 
         timer.sleep(Duration::milliseconds(1));
@@ -398,7 +396,7 @@ fn sender_goes_away_oneshot() {
             let mut timer = Timer::new().unwrap();
             timer.oneshot(Duration::milliseconds(1000))
         };
-        assert_eq!(rx.recv_opt(), Err(()));
+        assert!(rx.recv().is_err());
     }
 
     #[test]
@@ -407,7 +405,7 @@ fn sender_goes_away_period() {
             let mut timer = Timer::new().unwrap();
             timer.periodic(Duration::milliseconds(1000))
         };
-        assert_eq!(rx.recv_opt(), Err(()));
+        assert!(rx.recv().is_err());
     }
 
     #[test]
@@ -446,34 +444,34 @@ fn sleep_negative() {
     fn oneshot_zero() {
         let mut timer = Timer::new().unwrap();
         let rx = timer.oneshot(Duration::milliseconds(0));
-        rx.recv();
+        rx.recv().unwrap();
     }
 
     #[test]
     fn oneshot_negative() {
         let mut timer = Timer::new().unwrap();
         let rx = timer.oneshot(Duration::milliseconds(-1000000));
-        rx.recv();
+        rx.recv().unwrap();
     }
 
     #[test]
     fn periodic_zero() {
         let mut timer = Timer::new().unwrap();
         let rx = timer.periodic(Duration::milliseconds(0));
-        rx.recv();
-        rx.recv();
-        rx.recv();
-        rx.recv();
+        rx.recv().unwrap();
+        rx.recv().unwrap();
+        rx.recv().unwrap();
+        rx.recv().unwrap();
     }
 
     #[test]
     fn periodic_negative() {
         let mut timer = Timer::new().unwrap();
         let rx = timer.periodic(Duration::milliseconds(-1000000));
-        rx.recv();
-        rx.recv();
-        rx.recv();
-        rx.recv();
+        rx.recv().unwrap();
+        rx.recv().unwrap();
+        rx.recv().unwrap();
+        rx.recv().unwrap();
     }
 
 }
index e4888f3dd97d1c5ffe732c99f2da67ebcdbaecc4..b22090e0f163adad16ef5f63a34417097d678372 100644 (file)
@@ -384,7 +384,7 @@ fn test_tee_reader() {
         let mut r = TeeReader::new(MemReader::new(vec!(0, 1, 2)),
                                    Vec::new());
         assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap());
-        let (_, w) = r.unwrap();
+        let (_, w) = r.into_inner();
         assert_eq!(vec!(0, 1, 2), w);
     }
 
index 56d906c8b69e3ca19f2aa054c851f226b2585c29..aa1a0add0681a7f12ba7eb2e1169777a512522e3 100644 (file)
 pub mod task;
 pub mod thread;
 pub mod sync;
-pub mod comm;
 
 #[cfg(unix)]
 #[path = "sys/unix/mod.rs"] mod sys;
@@ -254,7 +253,7 @@ mod std {
     pub use cmp;
     pub use hash;
 
-    pub use comm; // used for select!()
+    pub use sync; // used for select!()
     pub use error; // used for try!()
     pub use fmt; // used for any formatting strings
     pub use io; // used for println!()
index 3606f5df5ca18cecd011218b36636a9b8c1323a1..51a0853687ebeae5438c3ad63b5d31d7745f9faa 100644 (file)
@@ -474,7 +474,7 @@ macro_rules! vec {
 ///
 /// ```
 /// use std::thread::Thread;
-/// use std::comm::channel;
+/// use std::sync::mpsc::channel;
 ///
 /// let (tx1, rx1) = channel();
 /// let (tx2, rx2) = channel();
@@ -485,21 +485,21 @@ macro_rules! vec {
 /// Thread::spawn(move|| { tx2.send(calculate_the_answer()) }).detach();
 ///
 /// select! (
-///     () = rx1.recv() => println!("the long running task finished first"),
+///     _ = rx1.recv() => println!("the long running task finished first"),
 ///     answer = rx2.recv() => {
-///         println!("the answer was: {}", answer);
+///         println!("the answer was: {}", answer.unwrap());
 ///     }
 /// )
 /// ```
 ///
-/// For more information about select, see the `std::comm::Select` structure.
+/// For more information about select, see the `std::sync::mpsc::Select` structure.
 #[macro_export]
 #[experimental]
 macro_rules! select {
     (
         $($name:pat = $rx:ident.$meth:ident() => $code:expr),+
     ) => ({
-        use std::comm::Select;
+        use std::sync::mpsc::Select;
         let sel = Select::new();
         $( let mut $rx = sel.handle(&$rx); )+
         unsafe {
index 6de49c38b732e98b6195de7e6d7d5210a802c7df..f2a0419e39196f584bb44fa645e3e6886fbc8948 100644 (file)
@@ -496,23 +496,25 @@ fn test_atanh() {
 
     #[test]
     fn test_real_consts() {
-        let pi: f32 = Float::pi();
-        let two_pi: f32 = Float::two_pi();
-        let frac_pi_2: f32 = Float::frac_pi_2();
-        let frac_pi_3: f32 = Float::frac_pi_3();
-        let frac_pi_4: f32 = Float::frac_pi_4();
-        let frac_pi_6: f32 = Float::frac_pi_6();
-        let frac_pi_8: f32 = Float::frac_pi_8();
-        let frac_1_pi: f32 = Float::frac_1_pi();
-        let frac_2_pi: f32 = Float::frac_2_pi();
-        let frac_2_sqrtpi: f32 = Float::frac_2_sqrtpi();
-        let sqrt2: f32 = Float::sqrt2();
-        let frac_1_sqrt2: f32 = Float::frac_1_sqrt2();
-        let e: f32 = Float::e();
-        let log2_e: f32 = Float::log2_e();
-        let log10_e: f32 = Float::log10_e();
-        let ln_2: f32 = Float::ln_2();
-        let ln_10: f32 = Float::ln_10();
+        use super::consts;
+
+        let pi: f32 = consts::PI;
+        let two_pi: f32 = consts::PI_2;
+        let frac_pi_2: f32 = consts::FRAC_PI_2;
+        let frac_pi_3: f32 = consts::FRAC_PI_3;
+        let frac_pi_4: f32 = consts::FRAC_PI_4;
+        let frac_pi_6: f32 = consts::FRAC_PI_6;
+        let frac_pi_8: f32 = consts::FRAC_PI_8;
+        let frac_1_pi: f32 = consts::FRAC_1_PI;
+        let frac_2_pi: f32 = consts::FRAC_2_PI;
+        let frac_2_sqrtpi: f32 = consts::FRAC_2_SQRTPI;
+        let sqrt2: f32 = consts::SQRT2;
+        let frac_1_sqrt2: f32 = consts::FRAC_1_SQRT2;
+        let e: f32 = consts::E;
+        let log2_e: f32 = consts::LOG2_E;
+        let log10_e: f32 = consts::LOG10_E;
+        let ln_2: f32 = consts::LN_2;
+        let ln_10: f32 = consts::LN_10;
 
         assert_approx_eq!(two_pi, 2f32 * pi);
         assert_approx_eq!(frac_pi_2, pi / 2f32);
index 50855d21b4ab89aac9a618ad40e99fa7dd912855..105a8a23bd104596cf0889590f453a39775f3adc 100644 (file)
@@ -499,23 +499,24 @@ fn test_atanh() {
 
     #[test]
     fn test_real_consts() {
-        let pi: f64 = Float::pi();
-        let two_pi: f64 = Float::two_pi();
-        let frac_pi_2: f64 = Float::frac_pi_2();
-        let frac_pi_3: f64 = Float::frac_pi_3();
-        let frac_pi_4: f64 = Float::frac_pi_4();
-        let frac_pi_6: f64 = Float::frac_pi_6();
-        let frac_pi_8: f64 = Float::frac_pi_8();
-        let frac_1_pi: f64 = Float::frac_1_pi();
-        let frac_2_pi: f64 = Float::frac_2_pi();
-        let frac_2_sqrtpi: f64 = Float::frac_2_sqrtpi();
-        let sqrt2: f64 = Float::sqrt2();
-        let frac_1_sqrt2: f64 = Float::frac_1_sqrt2();
-        let e: f64 = Float::e();
-        let log2_e: f64 = Float::log2_e();
-        let log10_e: f64 = Float::log10_e();
-        let ln_2: f64 = Float::ln_2();
-        let ln_10: f64 = Float::ln_10();
+        use super::consts;
+        let pi: f64 = consts::PI;
+        let two_pi: f64 = consts::PI_2;
+        let frac_pi_2: f64 = consts::FRAC_PI_2;
+        let frac_pi_3: f64 = consts::FRAC_PI_3;
+        let frac_pi_4: f64 = consts::FRAC_PI_4;
+        let frac_pi_6: f64 = consts::FRAC_PI_6;
+        let frac_pi_8: f64 = consts::FRAC_PI_8;
+        let frac_1_pi: f64 = consts::FRAC_1_PI;
+        let frac_2_pi: f64 = consts::FRAC_2_PI;
+        let frac_2_sqrtpi: f64 = consts::FRAC_2_SQRTPI;
+        let sqrt2: f64 = consts::SQRT2;
+        let frac_1_sqrt2: f64 = consts::FRAC_1_SQRT2;
+        let e: f64 = consts::E;
+        let log2_e: f64 = consts::LOG2_E;
+        let log10_e: f64 = consts::LOG10_E;
+        let ln_2: f64 = consts::LN_2;
+        let ln_10: f64 = consts::LN_10;
 
         assert_approx_eq!(two_pi, 2.0 * pi);
         assert_approx_eq!(frac_pi_2, pi / 2f64);
index 61ac89239f9fd5a657c82f36378e4cc5989f1997..754b13886af7eeb10f9e0e05f7e03563bb35e8eb 100644 (file)
@@ -1425,7 +1425,8 @@ mod arch_consts {
 #[cfg(test)]
 mod tests {
     use prelude::v1::*;
-    use option;
+
+    use iter::repeat;
     use os::{env, getcwd, getenv, make_absolute};
     use os::{split_paths, join_paths, setenv, unsetenv};
     use os;
@@ -1454,7 +1455,7 @@ fn test_num_cpus() {
     fn test_setenv() {
         let n = make_rand_name();
         setenv(n.as_slice(), "VALUE");
-        assert_eq!(getenv(n.as_slice()), option::Option::Some("VALUE".to_string()));
+        assert_eq!(getenv(n.as_slice()), Some("VALUE".to_string()));
     }
 
     #[test]
@@ -1462,7 +1463,7 @@ fn test_unsetenv() {
         let n = make_rand_name();
         setenv(n.as_slice(), "VALUE");
         unsetenv(n.as_slice());
-        assert_eq!(getenv(n.as_slice()), option::Option::None);
+        assert_eq!(getenv(n.as_slice()), None);
     }
 
     #[test]
@@ -1471,9 +1472,9 @@ fn test_setenv_overwrite() {
         let n = make_rand_name();
         setenv(n.as_slice(), "1");
         setenv(n.as_slice(), "2");
-        assert_eq!(getenv(n.as_slice()), option::Option::Some("2".to_string()));
+        assert_eq!(getenv(n.as_slice()), Some("2".to_string()));
         setenv(n.as_slice(), "");
-        assert_eq!(getenv(n.as_slice()), option::Option::Some("".to_string()));
+        assert_eq!(getenv(n.as_slice()), Some("".to_string()));
     }
 
     // Windows GetEnvironmentVariable requires some extra work to make sure
@@ -1490,7 +1491,7 @@ fn test_getenv_big() {
         let n = make_rand_name();
         setenv(n.as_slice(), s.as_slice());
         debug!("{}", s.clone());
-        assert_eq!(getenv(n.as_slice()), option::Option::Some(s));
+        assert_eq!(getenv(n.as_slice()), Some(s));
     }
 
     #[test]
@@ -1527,14 +1528,14 @@ fn test_env_getenv() {
             // MingW seems to set some funky environment variables like
             // "=C:=C:\MinGW\msys\1.0\bin" and "!::=::\" that are returned
             // from env() but not visible from getenv().
-            assert!(v2.is_none() || v2 == option::Option::Some(v));
+            assert!(v2.is_none() || v2 == Some(v));
         }
     }
 
     #[test]
     fn test_env_set_get_huge() {
         let n = make_rand_name();
-        let s = "x".repeat(10000).to_string();
+        let s = repeat("x").take(10000).collect::<String>();
         setenv(n.as_slice(), s.as_slice());
         assert_eq!(getenv(n.as_slice()), Some(s));
         unsetenv(n.as_slice());
@@ -1656,8 +1657,8 @@ fn get_fd(file: &File) -> libc::HANDLE {
         path.push("mmap_file.tmp");
         let size = MemoryMap::granularity() * 2;
         let mut file = File::open_mode(&path, Open, ReadWrite).unwrap();
-        file.seek(size as i64, SeekSet);
-        file.write_u8(0);
+        file.seek(size as i64, SeekSet).unwrap();
+        file.write_u8(0).unwrap();
 
         let chunk = MemoryMap::new(size / 2, &[
             MapOption::MapReadable,
index da4576ca36d80518802b8f389d91229f9566516b..5c415239c5e2fcbb34073f3d9703f3eb8ab63a03 100644 (file)
@@ -449,7 +449,6 @@ fn normalize_helper<'a>(v: &'a [u8], is_abs: bool) -> Option<Vec<&'a [u8]>> {
 mod tests {
     use prelude::v1::*;
     use str;
-    use super::*;
 
     macro_rules! t {
         (s: $path:expr, $exp:expr) => (
index e6fea07b3aa4362985d5cc2d495e1ba8783cda9c..9117827ffc2b467f08015d47ccb7361ef214e363 100644 (file)
@@ -1119,10 +1119,13 @@ fn prefix_len(p: Option<PathPrefix>) -> uint {
 
 #[cfg(test)]
 mod tests {
-    use prelude::v1::*;
-    use super::*;
+    use prelude::v1::Option::{mod, Some, None};
+    use prelude::v1::{Vec, Clone, AsSlice, SliceExt, CloneSliceExt, IteratorExt};
+    use prelude::v1::{DoubleEndedIteratorExt, Str, ToString, GenericPath};
+
     use super::PathPrefix::*;
     use super::parse_prefix;
+    use super::*;
 
     macro_rules! t {
         (s: $path:expr, $exp:expr) => (
index 95238c0dad9164f80fcf2502c353a2ae7d4b5984..0a7b9d07636ad7710ed786e8c1735152e10bdfbe 100644 (file)
@@ -337,7 +337,7 @@ fn drop(&mut self) {
 mod test {
     use prelude::v1::*;
 
-    use comm::channel;
+    use sync::mpsc::channel;
     use rand::Rng;
     use super::OsRng;
     use thread::Thread;
@@ -363,7 +363,7 @@ fn test_os_rng_tasks() {
 
             Thread::spawn(move|| {
                 // wait until all the tasks are ready to go.
-                rx.recv();
+                rx.recv().unwrap();
 
                 // deschedule to attempt to interleave things as much
                 // as possible (XXX: is this a good test?)
@@ -384,7 +384,7 @@ fn test_os_rng_tasks() {
 
         // start all the tasks
         for tx in txs.iter() {
-            tx.send(())
+            tx.send(()).unwrap();
         }
     }
 }
index 15a682ad3b8062bab267915eb445a1ac5fdc2284..55d50af3b8365c4b1086c472feb72def995402b8 100644 (file)
@@ -92,7 +92,7 @@ mod tests {
     use prelude::v1::*;
 
     use sync::{Arc, Barrier};
-    use comm::{channel, Empty};
+    use sync::mpsc::{channel, TryRecvError};
     use thread::Thread;
 
     #[test]
@@ -105,21 +105,21 @@ fn test_barrier() {
             let tx = tx.clone();
             Thread::spawn(move|| {
                 c.wait();
-                tx.send(true);
+                tx.send(true).unwrap();
             }).detach();
         }
 
         // At this point, all spawned tasks should be blocked,
         // so we shouldn't get anything from the port
         assert!(match rx.try_recv() {
-            Err(Empty) => true,
+            Err(TryRecvError::Empty) => true,
             _ => false,
         });
 
         barrier.wait();
         // Now, the barrier is cleared and we should get data.
         for _ in range(0u, 9) {
-            rx.recv();
+            rx.recv().unwrap();
         }
     }
 }
index 984b895b31d1eda6e01196a5df094b007e2602b1..28960c1574e92cd75e9febc82a5e3b19fc4ce538 100644 (file)
@@ -264,8 +264,8 @@ fn verify(&self, mutex: &sys_mutex::Mutex) {
 mod tests {
     use prelude::v1::*;
 
-    use comm::channel;
     use super::{StaticCondvar, CONDVAR_INIT};
+    use sync::mpsc::channel;
     use sync::{StaticMutex, MUTEX_INIT, Condvar, Mutex, Arc};
     use thread::Thread;
     use time::Duration;
@@ -314,25 +314,25 @@ fn notify_all() {
                 let mut cnt = lock.lock();
                 *cnt += 1;
                 if *cnt == N {
-                    tx.send(());
+                    tx.send(()).unwrap();
                 }
                 while *cnt != 0 {
                     cond.wait(&cnt);
                 }
-                tx.send(());
+                tx.send(()).unwrap();
             }).detach();
         }
         drop(tx);
 
         let &(ref lock, ref cond) = &*data;
-        rx.recv();
+        rx.recv().unwrap();
         let mut cnt = lock.lock();
         *cnt = 0;
         cond.notify_all();
         drop(cnt);
 
         for _ in range(0, N) {
-            rx.recv();
+            rx.recv().unwrap();
         }
     }
 
index a0e7236b8d29a69ce3ec208c1b28d82f22f257a5..e3620617d5735047ff4d39ef36f2f47f98d83205 100644 (file)
@@ -28,7 +28,7 @@
 use core::mem::replace;
 
 use self::FutureState::*;
-use comm::{Receiver, channel};
+use sync::mpsc::{Receiver, channel};
 use thunk::{Thunk};
 use thread::Thread;
 
@@ -122,8 +122,8 @@ pub fn from_receiver(rx: Receiver<A>) -> Future<A> {
          * waiting for the result to be received on the port.
          */
 
-        Future::from_fn(move|:| {
-            rx.recv()
+        Future::from_fn(move |:| {
+            rx.recv().unwrap()
         })
     }
 
@@ -141,7 +141,7 @@ pub fn spawn<F>(blk: F) -> Future<A>
 
         Thread::spawn(move |:| {
             // Don't panic if the other end has hung up
-            let _ = tx.send_opt(blk());
+            let _ = tx.send(blk());
         }).detach();
 
         Future::from_receiver(rx)
@@ -151,7 +151,7 @@ pub fn spawn<F>(blk: F) -> Future<A>
 #[cfg(test)]
 mod test {
     use prelude::v1::*;
-    use comm::channel;
+    use sync::mpsc::channel;
     use sync::Future;
     use thread::Thread;
 
@@ -164,7 +164,7 @@ fn test_from_value() {
     #[test]
     fn test_from_receiver() {
         let (tx, rx) = channel();
-        tx.send("whale".to_string());
+        tx.send("whale".to_string()).unwrap();
         let mut f = Future::from_receiver(rx);
         assert_eq!(f.get(), "whale");
     }
@@ -184,7 +184,7 @@ fn test_interface_get() {
     #[test]
     fn test_interface_unwrap() {
         let f = Future::from_value("fail".to_string());
-        assert_eq!(f.unwrap(), "fail");
+        assert_eq!(f.into_inner(), "fail");
     }
 
     #[test]
@@ -213,8 +213,8 @@ fn test_sendable_future() {
         let f = Future::spawn(move|| { expected });
         let _t = Thread::spawn(move|| {
             let mut f = f;
-            tx.send(f.get());
+            tx.send(f.get()).unwrap();
         });
-        assert_eq!(rx.recv(), expected);
+        assert_eq!(rx.recv().unwrap(), expected);
     }
 }
index 7605a6a96a005d150713a774ff97d2fda90abeff..2b7311e4e982b147656ec38f62f1984b154c2346 100644 (file)
@@ -32,6 +32,8 @@
 pub use self::task_pool::TaskPool;
 
 pub mod atomic;
+pub mod mpsc;
+
 mod barrier;
 mod condvar;
 mod future;
diff --git a/src/libstd/sync/mpsc/blocking.rs b/src/libstd/sync/mpsc/blocking.rs
new file mode 100644 (file)
index 0000000..412b716
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Generic support for building blocking abstractions.
+
+use thread::Thread;
+use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Ordering};
+use sync::Arc;
+use kinds::{Sync, Send};
+use kinds::marker::{NoSend, NoSync};
+use mem;
+use clone::Clone;
+
+struct Inner {
+    thread: Thread,
+    woken: AtomicBool,
+}
+
+unsafe impl Send for Inner {}
+unsafe impl Sync for Inner {}
+
+#[deriving(Clone)]
+pub struct SignalToken {
+    inner: Arc<Inner>,
+}
+
+pub struct WaitToken {
+    inner: Arc<Inner>,
+    no_send: NoSend,
+    no_sync: NoSync,
+}
+
+pub fn tokens() -> (WaitToken, SignalToken) {
+    let inner = Arc::new(Inner {
+        thread: Thread::current(),
+        woken: INIT_ATOMIC_BOOL,
+    });
+    let wait_token = WaitToken {
+        inner: inner.clone(),
+        no_send: NoSend,
+        no_sync: NoSync,
+    };
+    let signal_token = SignalToken {
+        inner: inner
+    };
+    (wait_token, signal_token)
+}
+
+impl SignalToken {
+    pub fn signal(&self) -> bool {
+        let wake = !self.inner.woken.compare_and_swap(false, true, Ordering::SeqCst);
+        if wake {
+            self.inner.thread.unpark();
+        }
+        wake
+    }
+
+    /// Convert to an unsafe uint value. Useful for storing in a pipe's state
+    /// flag.
+    #[inline]
+    pub unsafe fn cast_to_uint(self) -> uint {
+        mem::transmute(self.inner)
+    }
+
+    /// Convert from an unsafe uint value. Useful for retrieving a pipe's state
+    /// flag.
+    #[inline]
+    pub unsafe fn cast_from_uint(signal_ptr: uint) -> SignalToken {
+        SignalToken { inner: mem::transmute(signal_ptr) }
+    }
+
+}
+
+impl WaitToken {
+    pub fn wait(self) {
+        while !self.inner.woken.load(Ordering::SeqCst) {
+            Thread::park()
+        }
+    }
+}
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
new file mode 100644 (file)
index 0000000..e229490
--- /dev/null
@@ -0,0 +1,2079 @@
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Multi-producer, single-consumer communication primitives threads
+//!
+//! This module provides message-based communication over channels, concretely
+//! defined among three types:
+//!
+//! * `Sender`
+//! * `SyncSender`
+//! * `Receiver`
+//!
+//! A `Sender` or `SyncSender` is used to send data to a `Receiver`. Both
+//! senders are clone-able (multi-producer) such that many threads can send
+//! simultaneously to one receiver (single-consumer).  These channels are
+//!
+//! These channels come in two flavors:
+//!
+//! 1. An asynchronous, infinitely buffered channel. The `channel()` function
+//!    will return a `(Sender, Receiver)` tuple where all sends will be
+//!    **asynchronous** (they never block). The channel conceptually has an
+//!    infinite buffer.
+//!
+//! 2. A synchronous, bounded channel. The `sync_channel()` function will return
+//!    a `(SyncSender, Receiver)` tuple where the storage for pending messages
+//!    is a pre-allocated buffer of a fixed size. All sends will be
+//!    **synchronous** by blocking until there is buffer space available. Note
+//!    that a bound of 0 is allowed, causing the channel to become a
+//!    "rendezvous" channel where each sender atomically hands off a message to
+//!    a receiver.
+//!
+//! ## Disconnection
+//!
+//! The send and receive operations on channels will all return a `Result`
+//! indicating whether the operation succeeded or not. An unsuccessful operation
+//! is normally indicative of the other half of a channel having "hung up" by
+//! being dropped in its corresponding thread.
+//!
+//! Once half of a channel has been deallocated, most operations can no longer
+//! continue to make progress, so `Err` will be returned. Many applications will
+//! continue to `unwrap()` the results returned from this module, instigating a
+//! propagation of failure among threads if one unexpectedly dies.
+//!
+//! # Examples
+//!
+//! Simple usage:
+//!
+//! ```
+//! use std::thread::Thread;
+//! use std::sync::mpsc::channel;
+//!
+//! // Create a simple streaming channel
+//! let (tx, rx) = channel();
+//! Thread::spawn(move|| {
+//!     tx.send(10i).unwrap();
+//! }).detach();
+//! assert_eq!(rx.recv().unwrap(), 10i);
+//! ```
+//!
+//! Shared usage:
+//!
+//! ```
+//! use std::thread::Thread;
+//! use std::sync::mpsc::channel;
+//!
+//! // Create a shared channel that can be sent along from many threads
+//! // where tx is the sending half (tx for transmission), and rx is the receiving
+//! // half (rx for receiving).
+//! let (tx, rx) = channel();
+//! for i in range(0i, 10i) {
+//!     let tx = tx.clone();
+//!     Thread::spawn(move|| {
+//!         tx.send(i).unwrap();
+//!     }).detach()
+//! }
+//!
+//! for _ in range(0i, 10i) {
+//!     let j = rx.recv().unwrap();
+//!     assert!(0 <= j && j < 10);
+//! }
+//! ```
+//!
+//! Propagating panics:
+//!
+//! ```
+//! use std::sync::mpsc::channel;
+//!
+//! // The call to recv() will return an error because the channel has already
+//! // hung up (or been deallocated)
+//! let (tx, rx) = channel::<int>();
+//! drop(tx);
+//! assert!(rx.recv().is_err());
+//! ```
+//!
+//! Synchronous channels:
+//!
+//! ```
+//! use std::thread::Thread;
+//! use std::sync::mpsc::sync_channel;
+//!
+//! let (tx, rx) = sync_channel::<int>(0);
+//! Thread::spawn(move|| {
+//!     // This will wait for the parent task to start receiving
+//!     tx.send(53).unwrap();
+//! }).detach();
+//! rx.recv().unwrap();
+//! ```
+//!
+//! Reading from a channel with a timeout requires to use a Timer together
+//! with the channel. You can use the select! macro to select either and
+//! handle the timeout case. This first example will break out of the loop
+//! after 10 seconds no matter what:
+//!
+//! ```no_run
+//! use std::sync::mpsc::channel;
+//! use std::io::timer::Timer;
+//! use std::time::Duration;
+//!
+//! let (tx, rx) = channel::<int>();
+//! let mut timer = Timer::new().unwrap();
+//! let timeout = timer.oneshot(Duration::seconds(10));
+//!
+//! loop {
+//!     select! {
+//!         val = rx.recv() => println!("Received {}", val.unwrap()),
+//!         _ = timeout.recv() => {
+//!             println!("timed out, total time was more than 10 seconds");
+//!             break;
+//!         }
+//!     }
+//! }
+//! ```
+//!
+//! This second example is more costly since it allocates a new timer every
+//! time a message is received, but it allows you to timeout after the channel
+//! has been inactive for 5 seconds:
+//!
+//! ```no_run
+//! use std::sync::mpsc::channel;
+//! use std::io::timer::Timer;
+//! use std::time::Duration;
+//!
+//! let (tx, rx) = channel::<int>();
+//! let mut timer = Timer::new().unwrap();
+//!
+//! loop {
+//!     let timeout = timer.oneshot(Duration::seconds(5));
+//!
+//!     select! {
+//!         val = rx.recv() => println!("Received {}", val.unwrap()),
+//!         _ = timeout.recv() => {
+//!             println!("timed out, no message received in 5 seconds");
+//!             break;
+//!         }
+//!     }
+//! }
+//! ```
+
+// A description of how Rust's channel implementation works
+//
+// Channels are supposed to be the basic building block for all other
+// concurrent primitives that are used in Rust. As a result, the channel type
+// needs to be highly optimized, flexible, and broad enough for use everywhere.
+//
+// The choice of implementation of all channels is to be built on lock-free data
+// structures. The channels themselves are then consequently also lock-free data
+// structures. As always with lock-free code, this is a very "here be dragons"
+// territory, especially because I'm unaware of any academic papers that have
+// gone into great length about channels of these flavors.
+//
+// ## Flavors of channels
+//
+// From the perspective of a consumer of this library, there is only one flavor
+// of channel. This channel can be used as a stream and cloned to allow multiple
+// senders. Under the hood, however, there are actually three flavors of
+// channels in play.
+//
+// * Oneshots - these channels are highly optimized for the one-send use case.
+//              They contain as few atomics as possible and involve one and
+//              exactly one allocation.
+// * Streams - these channels are optimized for the non-shared use case. They
+//             use a different concurrent queue that is more tailored for this
+//             use case. The initial allocation of this flavor of channel is not
+//             optimized.
+// * Shared - this is the most general form of channel that this module offers,
+//            a channel with multiple senders. This type is as optimized as it
+//            can be, but the previous two types mentioned are much faster for
+//            their use-cases.
+//
+// ## Concurrent queues
+//
+// The basic idea of Rust's Sender/Receiver types is that send() never blocks, but
+// recv() obviously blocks. This means that under the hood there must be some
+// shared and concurrent queue holding all of the actual data.
+//
+// With two flavors of channels, two flavors of queues are also used. We have
+// chosen to use queues from a well-known author that are abbreviated as SPSC
+// and MPSC (single producer, single consumer and multiple producer, single
+// consumer). SPSC queues are used for streams while MPSC queues are used for
+// shared channels.
+//
+// ### SPSC optimizations
+//
+// The SPSC queue found online is essentially a linked list of nodes where one
+// half of the nodes are the "queue of data" and the other half of nodes are a
+// cache of unused nodes. The unused nodes are used such that an allocation is
+// not required on every push() and a free doesn't need to happen on every
+// pop().
+//
+// As found online, however, the cache of nodes is of an infinite size. This
+// means that if a channel at one point in its life had 50k items in the queue,
+// then the queue will always have the capacity for 50k items. I believed that
+// this was an unnecessary limitation of the implementation, so I have altered
+// the queue to optionally have a bound on the cache size.
+//
+// By default, streams will have an unbounded SPSC queue with a small-ish cache
+// size. The hope is that the cache is still large enough to have very fast
+// send() operations while not too large such that millions of channels can
+// coexist at once.
+//
+// ### MPSC optimizations
+//
+// Right now the MPSC queue has not been optimized. Like the SPSC queue, it uses
+// a linked list under the hood to earn its unboundedness, but I have not put
+// forth much effort into having a cache of nodes similar to the SPSC queue.
+//
+// For now, I believe that this is "ok" because shared channels are not the most
+// common type, but soon we may wish to revisit this queue choice and determine
+// another candidate for backend storage of shared channels.
+//
+// ## Overview of the Implementation
+//
+// Now that there's a little background on the concurrent queues used, it's
+// worth going into much more detail about the channels themselves. The basic
+// pseudocode for a send/recv are:
+//
+//
+//      send(t)                             recv()
+//        queue.push(t)                       return if queue.pop()
+//        if increment() == -1                deschedule {
+//          wakeup()                            if decrement() > 0
+//                                                cancel_deschedule()
+//                                            }
+//                                            queue.pop()
+//
+// As mentioned before, there are no locks in this implementation, only atomic
+// instructions are used.
+//
+// ### The internal atomic counter
+//
+// Every channel has a shared counter with each half to keep track of the size
+// of the queue. This counter is used to abort descheduling by the receiver and
+// to know when to wake up on the sending side.
+//
+// As seen in the pseudocode, senders will increment this count and receivers
+// will decrement the count. The theory behind this is that if a sender sees a
+// -1 count, it will wake up the receiver, and if the receiver sees a 1+ count,
+// then it doesn't need to block.
+//
+// The recv() method has a beginning call to pop(), and if successful, it needs
+// to decrement the count. It is a crucial implementation detail that this
+// decrement does *not* happen to the shared counter. If this were the case,
+// then it would be possible for the counter to be very negative when there were
+// no receivers waiting, in which case the senders would have to determine when
+// it was actually appropriate to wake up a receiver.
+//
+// Instead, the "steal count" is kept track of separately (not atomically
+// because it's only used by receivers), and then the decrement() call when
+// descheduling will lump in all of the recent steals into one large decrement.
+//
+// The implication of this is that if a sender sees a -1 count, then there's
+// guaranteed to be a waiter waiting!
+//
+// ## Native Implementation
+//
+// A major goal of these channels is to work seamlessly on and off the runtime.
+// All of the previous race conditions have been worded in terms of
+// scheduler-isms (which is obviously not available without the runtime).
+//
+// For now, native usage of channels (off the runtime) will fall back onto
+// mutexes/cond vars for descheduling/atomic decisions. The no-contention path
+// is still entirely lock-free, the "deschedule" blocks above are surrounded by
+// a mutex and the "wakeup" blocks involve grabbing a mutex and signaling on a
+// condition variable.
+//
+// ## Select
+//
+// Being able to support selection over channels has greatly influenced this
+// design, and not only does selection need to work inside the runtime, but also
+// outside the runtime.
+//
+// The implementation is fairly straightforward. The goal of select() is not to
+// return some data, but only to return which channel can receive data without
+// blocking. The implementation is essentially the entire blocking procedure
+// followed by an increment as soon as its woken up. The cancellation procedure
+// involves an increment and swapping out of to_wake to acquire ownership of the
+// task to unblock.
+//
+// Sadly this current implementation requires multiple allocations, so I have
+// seen the throughput of select() be much worse than it should be. I do not
+// believe that there is anything fundamental that needs to change about these
+// channels, however, in order to support a more efficient select().
+//
+// # Conclusion
+//
+// And now that you've seen all the races that I found and attempted to fix,
+// here's the code for you to find some more!
+
+use prelude::v1::*;
+
+use sync::Arc;
+use fmt;
+use kinds::marker;
+use mem;
+use cell::UnsafeCell;
+
+pub use self::select::{Select, Handle};
+use self::select::StartResult;
+use self::select::StartResult::*;
+use self::blocking::SignalToken;
+
+mod blocking;
+mod oneshot;
+mod select;
+mod shared;
+mod stream;
+mod sync;
+mod mpsc_queue;
+mod spsc_queue;
+
+/// The receiving-half of Rust's channel type. This half can only be owned by
+/// one task
+#[stable]
+pub struct Receiver<T> {
+    inner: UnsafeCell<Flavor<T>>,
+}
+
+// The receiver port can be sent from place to place, so long as it
+// is not used to receive non-sendable things.
+unsafe impl<T:Send> Send for Receiver<T> { }
+
+/// An iterator over messages on a receiver, this iterator will block
+/// whenever `next` is called, waiting for a new message, and `None` will be
+/// returned when the corresponding channel has hung up.
+#[stable]
+pub struct Iter<'a, T:'a> {
+    rx: &'a Receiver<T>
+}
+
+/// The sending-half of Rust's asynchronous channel type. This half can only be
+/// owned by one task, but it can be cloned to send to other tasks.
+#[stable]
+pub struct Sender<T> {
+    inner: UnsafeCell<Flavor<T>>,
+}
+
+// The send port can be sent from place to place, so long as it
+// is not used to send non-sendable things.
+unsafe impl<T:Send> Send for Sender<T> { }
+
+/// The sending-half of Rust's synchronous channel type. This half can only be
+/// owned by one task, but it can be cloned to send to other tasks.
+#[stable]
+pub struct SyncSender<T> {
+    inner: Arc<RacyCell<sync::Packet<T>>>,
+    // can't share in an arc
+    _marker: marker::NoSync,
+}
+
+/// An error returned from the `send` function on channels.
+///
+/// A `send` operation can only fail if the receiving end of a channel is
+/// disconnected, implying that the data could never be received. The error
+/// contains the data being sent as a payload so it can be recovered.
+#[deriving(PartialEq, Eq)]
+#[stable]
+pub struct SendError<T>(pub T);
+
+/// An error returned from the `recv` function on a `Receiver`.
+///
+/// The `recv` operation can only fail if the sending half of a channel is
+/// disconnected, implying that no further messages will ever be received.
+#[deriving(PartialEq, Eq, Clone, Copy)]
+#[stable]
+pub struct RecvError;
+
+/// This enumeration is the list of the possible reasons that try_recv could not
+/// return data when called.
+#[deriving(PartialEq, Clone, Copy)]
+#[stable]
+pub enum TryRecvError {
+    /// This channel is currently empty, but the sender(s) have not yet
+    /// disconnected, so data may yet become available.
+    #[stable]
+    Empty,
+
+    /// This channel's sending half has become disconnected, and there will
+    /// never be any more data received on this channel
+    #[stable]
+    Disconnected,
+}
+
+/// This enumeration is the list of the possible error outcomes for the
+/// `SyncSender::try_send` method.
+#[deriving(PartialEq, Clone)]
+#[stable]
+pub enum TrySendError<T> {
+    /// The data could not be sent on the channel because it would require that
+    /// the callee block to send the data.
+    ///
+    /// If this is a buffered channel, then the buffer is full at this time. If
+    /// this is not a buffered channel, then there is no receiver available to
+    /// acquire the data.
+    #[stable]
+    Full(T),
+
+    /// This channel's receiving half has disconnected, so the data could not be
+    /// sent. The data is returned back to the callee in this case.
+    #[stable]
+    Disconnected(T),
+}
+
+enum Flavor<T> {
+    Oneshot(Arc<RacyCell<oneshot::Packet<T>>>),
+    Stream(Arc<RacyCell<stream::Packet<T>>>),
+    Shared(Arc<RacyCell<shared::Packet<T>>>),
+    Sync(Arc<RacyCell<sync::Packet<T>>>),
+}
+
+#[doc(hidden)]
+trait UnsafeFlavor<T> {
+    fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>>;
+    unsafe fn inner_mut<'a>(&'a self) -> &'a mut Flavor<T> {
+        &mut *self.inner_unsafe().get()
+    }
+    unsafe fn inner<'a>(&'a self) -> &'a Flavor<T> {
+        &*self.inner_unsafe().get()
+    }
+}
+impl<T> UnsafeFlavor<T> for Sender<T> {
+    fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
+        &self.inner
+    }
+}
+impl<T> UnsafeFlavor<T> for Receiver<T> {
+    fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
+        &self.inner
+    }
+}
+
+/// Creates a new asynchronous channel, returning the sender/receiver halves.
+///
+/// All data sent on the sender will become available on the receiver, and no
+/// send will block the calling task (this channel has an "infinite buffer").
+///
+/// # Example
+///
+/// ```
+/// use std::sync::mpsc::channel;
+/// use std::thread::Thread;
+///
+/// // tx is is the sending half (tx for transmission), and rx is the receiving
+/// // half (rx for receiving).
+/// let (tx, rx) = channel();
+///
+/// // Spawn off an expensive computation
+/// Thread::spawn(move|| {
+/// #   fn expensive_computation() {}
+///     tx.send(expensive_computation()).unwrap();
+/// }).detach();
+///
+/// // Do some useful work for awhile
+///
+/// // Let's see what that answer was
+/// println!("{}", rx.recv().unwrap());
+/// ```
+#[stable]
+pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
+    let a = Arc::new(RacyCell::new(oneshot::Packet::new()));
+    (Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a)))
+}
+
+/// Creates a new synchronous, bounded channel.
+///
+/// Like asynchronous channels, the `Receiver` will block until a message
+/// becomes available. These channels differ greatly in the semantics of the
+/// sender from asynchronous channels, however.
+///
+/// This channel has an internal buffer on which messages will be queued. When
+/// the internal buffer becomes full, future sends will *block* waiting for the
+/// buffer to open up. Note that a buffer size of 0 is valid, in which case this
+/// becomes  "rendezvous channel" where each send will not return until a recv
+/// is paired with it.
+///
+/// As with asynchronous channels, all senders will panic in `send` if the
+/// `Receiver` has been destroyed.
+///
+/// # Example
+///
+/// ```
+/// use std::sync::mpsc::sync_channel;
+/// use std::thread::Thread;
+///
+/// let (tx, rx) = sync_channel(1);
+///
+/// // this returns immediately
+/// tx.send(1i).unwrap();
+///
+/// Thread::spawn(move|| {
+///     // this will block until the previous message has been received
+///     tx.send(2i).unwrap();
+/// }).detach();
+///
+/// assert_eq!(rx.recv().unwrap(), 1i);
+/// assert_eq!(rx.recv().unwrap(), 2i);
+/// ```
+#[stable]
+pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
+    let a = Arc::new(RacyCell::new(sync::Packet::new(bound)));
+    (SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a)))
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Sender
+////////////////////////////////////////////////////////////////////////////////
+
+impl<T: Send> Sender<T> {
+    fn new(inner: Flavor<T>) -> Sender<T> {
+        Sender {
+            inner: UnsafeCell::new(inner),
+        }
+    }
+
+    /// Attempts to send a value on this channel, returning it back if it could
+    /// not be sent.
+    ///
+    /// A successful send occurs when it is determined that the other end of
+    /// the channel has not hung up already. An unsuccessful send would be one
+    /// 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
+    /// hang up immediately after this function returns `Ok`.
+    ///
+    /// This method will never block the current thread.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// use std::sync::mpsc::channel;
+    ///
+    /// let (tx, rx) = channel();
+    ///
+    /// // This send is always successful
+    /// tx.send(1i).unwrap();
+    ///
+    /// // This send will fail because the receiver is gone
+    /// drop(rx);
+    /// assert_eq!(tx.send(1i).err().unwrap().0, 1);
+    /// ```
+    pub fn send(&self, t: T) -> Result<(), SendError<T>> {
+        let (new_inner, ret) = match *unsafe { self.inner() } {
+            Flavor::Oneshot(ref p) => {
+                unsafe {
+                    let p = p.get();
+                    if !(*p).sent() {
+                        return (*p).send(t).map_err(SendError);
+                    } else {
+                        let a =
+                            Arc::new(RacyCell::new(stream::Packet::new()));
+                        let rx = Receiver::new(Flavor::Stream(a.clone()));
+                        match (*p).upgrade(rx) {
+                            oneshot::UpSuccess => {
+                                let ret = (*a.get()).send(t);
+                                (a, ret)
+                            }
+                            oneshot::UpDisconnected => (a, Err(t)),
+                            oneshot::UpWoke(token) => {
+                                // This send cannot panic because the thread is
+                                // asleep (we're looking at it), so the receiver
+                                // can't go away.
+                                (*a.get()).send(t).ok().unwrap();
+                                token.signal();
+                                (a, Ok(()))
+                            }
+                        }
+                    }
+                }
+            }
+            Flavor::Stream(ref p) => return unsafe {
+                (*p.get()).send(t).map_err(SendError)
+            },
+            Flavor::Shared(ref p) => return unsafe {
+                (*p.get()).send(t).map_err(SendError)
+            },
+            Flavor::Sync(..) => unreachable!(),
+        };
+
+        unsafe {
+            let tmp = Sender::new(Flavor::Stream(new_inner));
+            mem::swap(self.inner_mut(), tmp.inner_mut());
+        }
+        ret.map_err(SendError)
+    }
+}
+
+#[stable]
+impl<T: Send> Clone for Sender<T> {
+    fn clone(&self) -> Sender<T> {
+        let (packet, sleeper, guard) = match *unsafe { self.inner() } {
+            Flavor::Oneshot(ref p) => {
+                let a = Arc::new(RacyCell::new(shared::Packet::new()));
+                unsafe {
+                    let guard = (*a.get()).postinit_lock();
+                    let rx = Receiver::new(Flavor::Shared(a.clone()));
+                    match (*p.get()).upgrade(rx) {
+                        oneshot::UpSuccess |
+                        oneshot::UpDisconnected => (a, None, guard),
+                        oneshot::UpWoke(task) => (a, Some(task), guard)
+                    }
+                }
+            }
+            Flavor::Stream(ref p) => {
+                let a = Arc::new(RacyCell::new(shared::Packet::new()));
+                unsafe {
+                    let guard = (*a.get()).postinit_lock();
+                    let rx = Receiver::new(Flavor::Shared(a.clone()));
+                    match (*p.get()).upgrade(rx) {
+                        stream::UpSuccess |
+                        stream::UpDisconnected => (a, None, guard),
+                        stream::UpWoke(task) => (a, Some(task), guard),
+                    }
+                }
+            }
+            Flavor::Shared(ref p) => {
+                unsafe { (*p.get()).clone_chan(); }
+                return Sender::new(Flavor::Shared(p.clone()));
+            }
+            Flavor::Sync(..) => unreachable!(),
+        };
+
+        unsafe {
+            (*packet.get()).inherit_blocker(sleeper, guard);
+
+            let tmp = Sender::new(Flavor::Shared(packet.clone()));
+            mem::swap(self.inner_mut(), tmp.inner_mut());
+        }
+        Sender::new(Flavor::Shared(packet))
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Sender<T> {
+    fn drop(&mut self) {
+        match *unsafe { self.inner_mut() } {
+            Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); },
+            Flavor::Stream(ref mut p) => unsafe { (*p.get()).drop_chan(); },
+            Flavor::Shared(ref mut p) => unsafe { (*p.get()).drop_chan(); },
+            Flavor::Sync(..) => unreachable!(),
+        }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// SyncSender
+////////////////////////////////////////////////////////////////////////////////
+
+impl<T: Send> SyncSender<T> {
+    fn new(inner: Arc<RacyCell<sync::Packet<T>>>) -> SyncSender<T> {
+        SyncSender { inner: inner, _marker: marker::NoSync }
+    }
+
+    /// Sends a value on this synchronous channel.
+    ///
+    /// This function will *block* until space in the internal buffer becomes
+    /// available or a receiver is available to hand off the message to.
+    ///
+    /// Note that a successful send does *not* guarantee that the receiver will
+    /// ever see the data if there is a buffer on this channel. Items may be
+    /// enqueued in the internal buffer for the receiver to receive at a later
+    /// time. If the buffer size is 0, however, it can be guaranteed that the
+    /// receiver has indeed received the data if this function returns success.
+    ///
+    /// This function will never panic, but it may return `Err` if the
+    /// `Receiver` has disconnected and is no longer able to receive
+    /// information.
+    #[stable]
+    pub fn send(&self, t: T) -> Result<(), SendError<T>> {
+        unsafe { (*self.inner.get()).send(t).map_err(SendError) }
+    }
+
+    /// Attempts to send a value on this channel without blocking.
+    ///
+    /// This method differs from `send` by returning immediately if the
+    /// channel's buffer is full or no receiver is waiting to acquire some
+    /// data. Compared with `send`, this function has two failure cases
+    /// instead of one (one for disconnection, one for a full buffer).
+    ///
+    /// See `SyncSender::send` for notes about guarantees of whether the
+    /// receiver has received the data or not if this function is successful.
+    #[stable]
+    pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
+        unsafe { (*self.inner.get()).try_send(t) }
+    }
+}
+
+#[stable]
+impl<T: Send> Clone for SyncSender<T> {
+    fn clone(&self) -> SyncSender<T> {
+        unsafe { (*self.inner.get()).clone_chan(); }
+        return SyncSender::new(self.inner.clone());
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for SyncSender<T> {
+    fn drop(&mut self) {
+        unsafe { (*self.inner.get()).drop_chan(); }
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Receiver
+////////////////////////////////////////////////////////////////////////////////
+
+impl<T: Send> Receiver<T> {
+    fn new(inner: Flavor<T>) -> Receiver<T> {
+        Receiver { inner: UnsafeCell::new(inner) }
+    }
+
+    /// Attempts to return a pending value on this receiver without blocking
+    ///
+    /// This method will never block the caller in order to wait for data to
+    /// become available. Instead, this will always return immediately with a
+    /// possible option of pending data on the channel.
+    ///
+    /// This is useful for a flavor of "optimistic check" before deciding to
+    /// block on a receiver.
+    #[stable]
+    pub fn try_recv(&self) -> Result<T, TryRecvError> {
+        loop {
+            let new_port = match *unsafe { self.inner() } {
+                Flavor::Oneshot(ref p) => {
+                    match unsafe { (*p.get()).try_recv() } {
+                        Ok(t) => return Ok(t),
+                        Err(oneshot::Empty) => return Err(TryRecvError::Empty),
+                        Err(oneshot::Disconnected) => {
+                            return Err(TryRecvError::Disconnected)
+                        }
+                        Err(oneshot::Upgraded(rx)) => rx,
+                    }
+                }
+                Flavor::Stream(ref p) => {
+                    match unsafe { (*p.get()).try_recv() } {
+                        Ok(t) => return Ok(t),
+                        Err(stream::Empty) => return Err(TryRecvError::Empty),
+                        Err(stream::Disconnected) => {
+                            return Err(TryRecvError::Disconnected)
+                        }
+                        Err(stream::Upgraded(rx)) => rx,
+                    }
+                }
+                Flavor::Shared(ref p) => {
+                    match unsafe { (*p.get()).try_recv() } {
+                        Ok(t) => return Ok(t),
+                        Err(shared::Empty) => return Err(TryRecvError::Empty),
+                        Err(shared::Disconnected) => {
+                            return Err(TryRecvError::Disconnected)
+                        }
+                    }
+                }
+                Flavor::Sync(ref p) => {
+                    match unsafe { (*p.get()).try_recv() } {
+                        Ok(t) => return Ok(t),
+                        Err(sync::Empty) => return Err(TryRecvError::Empty),
+                        Err(sync::Disconnected) => {
+                            return Err(TryRecvError::Disconnected)
+                        }
+                    }
+                }
+            };
+            unsafe {
+                mem::swap(self.inner_mut(),
+                          new_port.inner_mut());
+            }
+        }
+    }
+
+    /// Attempt to wait for a value on this receiver, returning an error if the
+    /// corresponding channel has hung up.
+    ///
+    /// This function will always block the current thread if there is no data
+    /// available and it's possible for more data to be sent. Once a message is
+    /// sent to the corresponding `Sender`, then this receiver will wake up and
+    /// return that message.
+    ///
+    /// If the corresponding `Sender` has disconnected, or it disconnects while
+    /// this call is blocking, this call will wake up and return `Err` to
+    /// indicate that no more messages can ever be received on this channel.
+    #[stable]
+    pub fn recv(&self) -> Result<T, RecvError> {
+        loop {
+            let new_port = match *unsafe { self.inner() } {
+                Flavor::Oneshot(ref p) => {
+                    match unsafe { (*p.get()).recv() } {
+                        Ok(t) => return Ok(t),
+                        Err(oneshot::Empty) => return unreachable!(),
+                        Err(oneshot::Disconnected) => return Err(RecvError),
+                        Err(oneshot::Upgraded(rx)) => rx,
+                    }
+                }
+                Flavor::Stream(ref p) => {
+                    match unsafe { (*p.get()).recv() } {
+                        Ok(t) => return Ok(t),
+                        Err(stream::Empty) => return unreachable!(),
+                        Err(stream::Disconnected) => return Err(RecvError),
+                        Err(stream::Upgraded(rx)) => rx,
+                    }
+                }
+                Flavor::Shared(ref p) => {
+                    match unsafe { (*p.get()).recv() } {
+                        Ok(t) => return Ok(t),
+                        Err(shared::Empty) => return unreachable!(),
+                        Err(shared::Disconnected) => return Err(RecvError),
+                    }
+                }
+                Flavor::Sync(ref p) => return unsafe {
+                    (*p.get()).recv().map_err(|()| RecvError)
+                }
+            };
+            unsafe {
+                mem::swap(self.inner_mut(), new_port.inner_mut());
+            }
+        }
+    }
+
+    /// Returns an iterator that will block waiting for messages, but never
+    /// `panic!`. It will return `None` when the channel has hung up.
+    #[stable]
+    pub fn iter(&self) -> Iter<T> {
+        Iter { rx: self }
+    }
+}
+
+impl<T: Send> select::Packet for Receiver<T> {
+    fn can_recv(&self) -> bool {
+        loop {
+            let new_port = match *unsafe { self.inner() } {
+                Flavor::Oneshot(ref p) => {
+                    match unsafe { (*p.get()).can_recv() } {
+                        Ok(ret) => return ret,
+                        Err(upgrade) => upgrade,
+                    }
+                }
+                Flavor::Stream(ref p) => {
+                    match unsafe { (*p.get()).can_recv() } {
+                        Ok(ret) => return ret,
+                        Err(upgrade) => upgrade,
+                    }
+                }
+                Flavor::Shared(ref p) => {
+                    return unsafe { (*p.get()).can_recv() };
+                }
+                Flavor::Sync(ref p) => {
+                    return unsafe { (*p.get()).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 unsafe { (*p.get()).start_selection(token) } {
+                        oneshot::SelSuccess => return Installed,
+                        oneshot::SelCanceled => return Abort,
+                        oneshot::SelUpgraded(t, rx) => (t, rx),
+                    }
+                }
+                Flavor::Stream(ref p) => {
+                    match unsafe { (*p.get()).start_selection(token) } {
+                        stream::SelSuccess => return Installed,
+                        stream::SelCanceled => return Abort,
+                        stream::SelUpgraded(t, rx) => (t, rx),
+                    }
+                }
+                Flavor::Shared(ref p) => {
+                    return unsafe { (*p.get()).start_selection(token) };
+                }
+                Flavor::Sync(ref p) => {
+                    return unsafe { (*p.get()).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) => unsafe { (*p.get()).abort_selection() },
+                Flavor::Stream(ref p) => unsafe {
+                    (*p.get()).abort_selection(was_upgrade)
+                },
+                Flavor::Shared(ref p) => return unsafe {
+                    (*p.get()).abort_selection(was_upgrade)
+                },
+                Flavor::Sync(ref p) => return unsafe {
+                    (*p.get()).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());
+            }
+        }
+    }
+}
+
+#[unstable]
+impl<'a, T: Send> Iterator<T> for Iter<'a, T> {
+    fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Receiver<T> {
+    fn drop(&mut self) {
+        match *unsafe { self.inner_mut() } {
+            Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); },
+            Flavor::Stream(ref mut p) => unsafe { (*p.get()).drop_port(); },
+            Flavor::Shared(ref mut p) => unsafe { (*p.get()).drop_port(); },
+            Flavor::Sync(ref mut p) => unsafe { (*p.get()).drop_port(); },
+        }
+    }
+}
+
+/// A version of `UnsafeCell` intended for use in concurrent data
+/// structures (for example, you might put it in an `Arc`).
+struct RacyCell<T>(pub UnsafeCell<T>);
+
+impl<T> RacyCell<T> {
+
+    fn new(value: T) -> RacyCell<T> {
+        RacyCell(UnsafeCell { value: value })
+    }
+
+    unsafe fn get(&self) -> *mut T {
+        self.0.get()
+    }
+
+}
+
+unsafe impl<T:Send> Send for RacyCell<T> { }
+
+unsafe impl<T> Sync for RacyCell<T> { } // Oh dear
+
+impl<T> fmt::Show for SendError<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "sending on a closed channel".fmt(f)
+    }
+}
+
+impl<T> fmt::Show for TrySendError<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            TrySendError::Full(..) => {
+                "sending on a full channel".fmt(f)
+            }
+            TrySendError::Disconnected(..) => {
+                "sending on a closed channel".fmt(f)
+            }
+        }
+    }
+}
+
+impl fmt::Show for RecvError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "receiving on a closed channel".fmt(f)
+    }
+}
+
+impl fmt::Show for TryRecvError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            TryRecvError::Empty => {
+                "receiving on an empty channel".fmt(f)
+            }
+            TryRecvError::Disconnected => {
+                "receiving on a closed channel".fmt(f)
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::v1::*;
+
+    use os;
+    use super::*;
+    use thread::Thread;
+
+    pub fn stress_factor() -> uint {
+        match os::getenv("RUST_TEST_STRESS") {
+            Some(val) => val.parse().unwrap(),
+            None => 1,
+        }
+    }
+
+    #[test]
+    fn smoke() {
+        let (tx, rx) = channel::<int>();
+        tx.send(1).unwrap();
+        assert_eq!(rx.recv().unwrap(), 1);
+    }
+
+    #[test]
+    fn drop_full() {
+        let (tx, _rx) = channel();
+        tx.send(box 1i).unwrap();
+    }
+
+    #[test]
+    fn drop_full_shared() {
+        let (tx, _rx) = channel();
+        drop(tx.clone());
+        drop(tx.clone());
+        tx.send(box 1i).unwrap();
+    }
+
+    #[test]
+    fn smoke_shared() {
+        let (tx, rx) = channel::<int>();
+        tx.send(1).unwrap();
+        assert_eq!(rx.recv().unwrap(), 1);
+        let tx = tx.clone();
+        tx.send(1).unwrap();
+        assert_eq!(rx.recv().unwrap(), 1);
+    }
+
+    #[test]
+    fn smoke_threads() {
+        let (tx, rx) = channel::<int>();
+        let _t = Thread::spawn(move|| {
+            tx.send(1).unwrap();
+        });
+        assert_eq!(rx.recv().unwrap(), 1);
+    }
+
+    #[test]
+    fn smoke_port_gone() {
+        let (tx, rx) = channel::<int>();
+        drop(rx);
+        assert!(tx.send(1).is_err());
+    }
+
+    #[test]
+    fn smoke_shared_port_gone() {
+        let (tx, rx) = channel::<int>();
+        drop(rx);
+        assert!(tx.send(1).is_err())
+    }
+
+    #[test]
+    fn smoke_shared_port_gone2() {
+        let (tx, rx) = channel::<int>();
+        drop(rx);
+        let tx2 = tx.clone();
+        drop(tx);
+        assert!(tx2.send(1).is_err());
+    }
+
+    #[test]
+    fn port_gone_concurrent() {
+        let (tx, rx) = channel::<int>();
+        let _t = Thread::spawn(move|| {
+            rx.recv().unwrap();
+        });
+        while tx.send(1).is_ok() {}
+    }
+
+    #[test]
+    fn port_gone_concurrent_shared() {
+        let (tx, rx) = channel::<int>();
+        let tx2 = tx.clone();
+        let _t = Thread::spawn(move|| {
+            rx.recv().unwrap();
+        });
+        while tx.send(1).is_ok() && tx2.send(1).is_ok() {}
+    }
+
+    #[test]
+    fn smoke_chan_gone() {
+        let (tx, rx) = channel::<int>();
+        drop(tx);
+        assert!(rx.recv().is_err());
+    }
+
+    #[test]
+    fn smoke_chan_gone_shared() {
+        let (tx, rx) = channel::<()>();
+        let tx2 = tx.clone();
+        drop(tx);
+        drop(tx2);
+        assert!(rx.recv().is_err());
+    }
+
+    #[test]
+    fn chan_gone_concurrent() {
+        let (tx, rx) = channel::<int>();
+        let _t = Thread::spawn(move|| {
+            tx.send(1).unwrap();
+            tx.send(1).unwrap();
+        });
+        while rx.recv().is_ok() {}
+    }
+
+    #[test]
+    fn stress() {
+        let (tx, rx) = channel::<int>();
+        let t = Thread::spawn(move|| {
+            for _ in range(0u, 10000) { tx.send(1i).unwrap(); }
+        });
+        for _ in range(0u, 10000) {
+            assert_eq!(rx.recv().unwrap(), 1);
+        }
+        t.join().ok().unwrap();
+    }
+
+    #[test]
+    fn stress_shared() {
+        static AMT: uint = 10000;
+        static NTHREADS: uint = 8;
+        let (tx, rx) = channel::<int>();
+
+        let t = Thread::spawn(move|| {
+            for _ in range(0, AMT * NTHREADS) {
+                assert_eq!(rx.recv().unwrap(), 1);
+            }
+            match rx.try_recv() {
+                Ok(..) => panic!(),
+                _ => {}
+            }
+        });
+
+        for _ in range(0, NTHREADS) {
+            let tx = tx.clone();
+            Thread::spawn(move|| {
+                for _ in range(0, AMT) { tx.send(1).unwrap(); }
+            }).detach();
+        }
+        drop(tx);
+        t.join().ok().unwrap();
+    }
+
+    #[test]
+    fn send_from_outside_runtime() {
+        let (tx1, rx1) = channel::<()>();
+        let (tx2, rx2) = channel::<int>();
+        let t1 = Thread::spawn(move|| {
+            tx1.send(()).unwrap();
+            for _ in range(0i, 40) {
+                assert_eq!(rx2.recv().unwrap(), 1);
+            }
+        });
+        rx1.recv().unwrap();
+        let t2 = Thread::spawn(move|| {
+            for _ in range(0i, 40) {
+                tx2.send(1).unwrap();
+            }
+        });
+        t1.join().ok().unwrap();
+        t2.join().ok().unwrap();
+    }
+
+    #[test]
+    fn recv_from_outside_runtime() {
+        let (tx, rx) = channel::<int>();
+        let t = Thread::spawn(move|| {
+            for _ in range(0i, 40) {
+                assert_eq!(rx.recv().unwrap(), 1);
+            }
+        });
+        for _ in range(0u, 40) {
+            tx.send(1).unwrap();
+        }
+        t.join().ok().unwrap();
+    }
+
+    #[test]
+    fn no_runtime() {
+        let (tx1, rx1) = channel::<int>();
+        let (tx2, rx2) = channel::<int>();
+        let t1 = Thread::spawn(move|| {
+            assert_eq!(rx1.recv().unwrap(), 1);
+            tx2.send(2).unwrap();
+        });
+        let t2 = Thread::spawn(move|| {
+            tx1.send(1).unwrap();
+            assert_eq!(rx2.recv().unwrap(), 2);
+        });
+        t1.join().ok().unwrap();
+        t2.join().ok().unwrap();
+    }
+
+    #[test]
+    fn oneshot_single_thread_close_port_first() {
+        // Simple test of closing without sending
+        let (_tx, rx) = channel::<int>();
+        drop(rx);
+    }
+
+    #[test]
+    fn oneshot_single_thread_close_chan_first() {
+        // Simple test of closing without sending
+        let (tx, _rx) = channel::<int>();
+        drop(tx);
+    }
+
+    #[test]
+    fn oneshot_single_thread_send_port_close() {
+        // Testing that the sender cleans up the payload if receiver is closed
+        let (tx, rx) = channel::<Box<int>>();
+        drop(rx);
+        assert!(tx.send(box 0).is_err());
+    }
+
+    #[test]
+    fn oneshot_single_thread_recv_chan_close() {
+        // Receiving on a closed chan will panic
+        let res = Thread::spawn(move|| {
+            let (tx, rx) = channel::<int>();
+            drop(tx);
+            rx.recv().unwrap();
+        }).join();
+        // What is our res?
+        assert!(res.is_err());
+    }
+
+    #[test]
+    fn oneshot_single_thread_send_then_recv() {
+        let (tx, rx) = channel::<Box<int>>();
+        tx.send(box 10).unwrap();
+        assert!(rx.recv().unwrap() == box 10);
+    }
+
+    #[test]
+    fn oneshot_single_thread_try_send_open() {
+        let (tx, rx) = channel::<int>();
+        assert!(tx.send(10).is_ok());
+        assert!(rx.recv().unwrap() == 10);
+    }
+
+    #[test]
+    fn oneshot_single_thread_try_send_closed() {
+        let (tx, rx) = channel::<int>();
+        drop(rx);
+        assert!(tx.send(10).is_err());
+    }
+
+    #[test]
+    fn oneshot_single_thread_try_recv_open() {
+        let (tx, rx) = channel::<int>();
+        tx.send(10).unwrap();
+        assert!(rx.recv() == Ok(10));
+    }
+
+    #[test]
+    fn oneshot_single_thread_try_recv_closed() {
+        let (tx, rx) = channel::<int>();
+        drop(tx);
+        assert!(rx.recv().is_err());
+    }
+
+    #[test]
+    fn oneshot_single_thread_peek_data() {
+        let (tx, rx) = channel::<int>();
+        assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
+        tx.send(10).unwrap();
+        assert_eq!(rx.try_recv(), Ok(10));
+    }
+
+    #[test]
+    fn oneshot_single_thread_peek_close() {
+        let (tx, rx) = channel::<int>();
+        drop(tx);
+        assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
+        assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
+    }
+
+    #[test]
+    fn oneshot_single_thread_peek_open() {
+        let (_tx, rx) = channel::<int>();
+        assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
+    }
+
+    #[test]
+    fn oneshot_multi_task_recv_then_send() {
+        let (tx, rx) = channel::<Box<int>>();
+        let _t = Thread::spawn(move|| {
+            assert!(rx.recv().unwrap() == box 10);
+        });
+
+        tx.send(box 10).unwrap();
+    }
+
+    #[test]
+    fn oneshot_multi_task_recv_then_close() {
+        let (tx, rx) = channel::<Box<int>>();
+        let _t = Thread::spawn(move|| {
+            drop(tx);
+        });
+        let res = Thread::spawn(move|| {
+            assert!(rx.recv().unwrap() == box 10);
+        }).join();
+        assert!(res.is_err());
+    }
+
+    #[test]
+    fn oneshot_multi_thread_close_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = channel::<int>();
+            let _t = Thread::spawn(move|| {
+                drop(rx);
+            });
+            drop(tx);
+        }
+    }
+
+    #[test]
+    fn oneshot_multi_thread_send_close_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = channel::<int>();
+            let _t = Thread::spawn(move|| {
+                drop(rx);
+            });
+            let _ = Thread::spawn(move|| {
+                tx.send(1).unwrap();
+            }).join();
+        }
+    }
+
+    #[test]
+    fn oneshot_multi_thread_recv_close_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = channel::<int>();
+            Thread::spawn(move|| {
+                let res = Thread::spawn(move|| {
+                    rx.recv().unwrap();
+                }).join();
+                assert!(res.is_err());
+            }).detach();
+            let _t = Thread::spawn(move|| {
+                Thread::spawn(move|| {
+                    drop(tx);
+                }).detach();
+            });
+        }
+    }
+
+    #[test]
+    fn oneshot_multi_thread_send_recv_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = channel();
+            let _t = Thread::spawn(move|| {
+                tx.send(box 10i).unwrap();
+            });
+            assert!(rx.recv().unwrap() == box 10i);
+        }
+    }
+
+    #[test]
+    fn stream_send_recv_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = channel();
+
+            send(tx, 0);
+            recv(rx, 0);
+
+            fn send(tx: Sender<Box<int>>, i: int) {
+                if i == 10 { return }
+
+                Thread::spawn(move|| {
+                    tx.send(box i).unwrap();
+                    send(tx, i + 1);
+                }).detach();
+            }
+
+            fn recv(rx: Receiver<Box<int>>, i: int) {
+                if i == 10 { return }
+
+                Thread::spawn(move|| {
+                    assert!(rx.recv().unwrap() == box i);
+                    recv(rx, i + 1);
+                }).detach();
+            }
+        }
+    }
+
+    #[test]
+    fn recv_a_lot() {
+        // Regression test that we don't run out of stack in scheduler context
+        let (tx, rx) = channel();
+        for _ in range(0i, 10000) { tx.send(()).unwrap(); }
+        for _ in range(0i, 10000) { rx.recv().unwrap(); }
+    }
+
+    #[test]
+    fn shared_chan_stress() {
+        let (tx, rx) = channel();
+        let total = stress_factor() + 100;
+        for _ in range(0, total) {
+            let tx = tx.clone();
+            Thread::spawn(move|| {
+                tx.send(()).unwrap();
+            }).detach();
+        }
+
+        for _ in range(0, total) {
+            rx.recv().unwrap();
+        }
+    }
+
+    #[test]
+    fn test_nested_recv_iter() {
+        let (tx, rx) = channel::<int>();
+        let (total_tx, total_rx) = channel::<int>();
+
+        let _t = Thread::spawn(move|| {
+            let mut acc = 0;
+            for x in rx.iter() {
+                acc += x;
+            }
+            total_tx.send(acc).unwrap();
+        });
+
+        tx.send(3).unwrap();
+        tx.send(1).unwrap();
+        tx.send(2).unwrap();
+        drop(tx);
+        assert_eq!(total_rx.recv().unwrap(), 6);
+    }
+
+    #[test]
+    fn test_recv_iter_break() {
+        let (tx, rx) = channel::<int>();
+        let (count_tx, count_rx) = channel();
+
+        let _t = Thread::spawn(move|| {
+            let mut count = 0;
+            for x in rx.iter() {
+                if count >= 3 {
+                    break;
+                } else {
+                    count += x;
+                }
+            }
+            count_tx.send(count).unwrap();
+        });
+
+        tx.send(2).unwrap();
+        tx.send(2).unwrap();
+        tx.send(2).unwrap();
+        let _ = tx.send(2);
+        drop(tx);
+        assert_eq!(count_rx.recv().unwrap(), 4);
+    }
+
+    #[test]
+    fn try_recv_states() {
+        let (tx1, rx1) = channel::<int>();
+        let (tx2, rx2) = channel::<()>();
+        let (tx3, rx3) = channel::<()>();
+        let _t = Thread::spawn(move|| {
+            rx2.recv().unwrap();
+            tx1.send(1).unwrap();
+            tx3.send(()).unwrap();
+            rx2.recv().unwrap();
+            drop(tx1);
+            tx3.send(()).unwrap();
+        });
+
+        assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty));
+        tx2.send(()).unwrap();
+        rx3.recv().unwrap();
+        assert_eq!(rx1.try_recv(), Ok(1));
+        assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty));
+        tx2.send(()).unwrap();
+        rx3.recv().unwrap();
+        assert_eq!(rx1.try_recv(), Err(TryRecvError::Disconnected));
+    }
+
+    // This bug used to end up in a livelock inside of the Receiver destructor
+    // because the internal state of the Shared packet was corrupted
+    #[test]
+    fn destroy_upgraded_shared_port_when_sender_still_active() {
+        let (tx, rx) = channel();
+        let (tx2, rx2) = channel();
+        let _t = Thread::spawn(move|| {
+            rx.recv().unwrap(); // wait on a oneshot
+            drop(rx);  // destroy a shared
+            tx2.send(()).unwrap();
+        });
+        // make sure the other task has gone to sleep
+        for _ in range(0u, 5000) { Thread::yield_now(); }
+
+        // upgrade to a shared chan and send a message
+        let t = tx.clone();
+        drop(tx);
+        t.send(()).unwrap();
+
+        // wait for the child task to exit before we exit
+        rx2.recv().unwrap();
+    }
+}
+
+#[cfg(test)]
+mod sync_tests {
+    use prelude::v1::*;
+
+    use os;
+    use thread::Thread;
+    use super::*;
+
+    pub fn stress_factor() -> uint {
+        match os::getenv("RUST_TEST_STRESS") {
+            Some(val) => val.parse().unwrap(),
+            None => 1,
+        }
+    }
+
+    #[test]
+    fn smoke() {
+        let (tx, rx) = sync_channel::<int>(1);
+        tx.send(1).unwrap();
+        assert_eq!(rx.recv().unwrap(), 1);
+    }
+
+    #[test]
+    fn drop_full() {
+        let (tx, _rx) = sync_channel(1);
+        tx.send(box 1i).unwrap();
+    }
+
+    #[test]
+    fn smoke_shared() {
+        let (tx, rx) = sync_channel::<int>(1);
+        tx.send(1).unwrap();
+        assert_eq!(rx.recv().unwrap(), 1);
+        let tx = tx.clone();
+        tx.send(1).unwrap();
+        assert_eq!(rx.recv().unwrap(), 1);
+    }
+
+    #[test]
+    fn smoke_threads() {
+        let (tx, rx) = sync_channel::<int>(0);
+        let _t = Thread::spawn(move|| {
+            tx.send(1).unwrap();
+        });
+        assert_eq!(rx.recv().unwrap(), 1);
+    }
+
+    #[test]
+    fn smoke_port_gone() {
+        let (tx, rx) = sync_channel::<int>(0);
+        drop(rx);
+        assert!(tx.send(1).is_err());
+    }
+
+    #[test]
+    fn smoke_shared_port_gone2() {
+        let (tx, rx) = sync_channel::<int>(0);
+        drop(rx);
+        let tx2 = tx.clone();
+        drop(tx);
+        assert!(tx2.send(1).is_err());
+    }
+
+    #[test]
+    fn port_gone_concurrent() {
+        let (tx, rx) = sync_channel::<int>(0);
+        let _t = Thread::spawn(move|| {
+            rx.recv().unwrap();
+        });
+        while tx.send(1).is_ok() {}
+    }
+
+    #[test]
+    fn port_gone_concurrent_shared() {
+        let (tx, rx) = sync_channel::<int>(0);
+        let tx2 = tx.clone();
+        let _t = Thread::spawn(move|| {
+            rx.recv().unwrap();
+        });
+        while tx.send(1).is_ok() && tx2.send(1).is_ok() {}
+    }
+
+    #[test]
+    fn smoke_chan_gone() {
+        let (tx, rx) = sync_channel::<int>(0);
+        drop(tx);
+        assert!(rx.recv().is_err());
+    }
+
+    #[test]
+    fn smoke_chan_gone_shared() {
+        let (tx, rx) = sync_channel::<()>(0);
+        let tx2 = tx.clone();
+        drop(tx);
+        drop(tx2);
+        assert!(rx.recv().is_err());
+    }
+
+    #[test]
+    fn chan_gone_concurrent() {
+        let (tx, rx) = sync_channel::<int>(0);
+        Thread::spawn(move|| {
+            tx.send(1).unwrap();
+            tx.send(1).unwrap();
+        }).detach();
+        while rx.recv().is_ok() {}
+    }
+
+    #[test]
+    fn stress() {
+        let (tx, rx) = sync_channel::<int>(0);
+        Thread::spawn(move|| {
+            for _ in range(0u, 10000) { tx.send(1).unwrap(); }
+        }).detach();
+        for _ in range(0u, 10000) {
+            assert_eq!(rx.recv().unwrap(), 1);
+        }
+    }
+
+    #[test]
+    fn stress_shared() {
+        static AMT: uint = 1000;
+        static NTHREADS: uint = 8;
+        let (tx, rx) = sync_channel::<int>(0);
+        let (dtx, drx) = sync_channel::<()>(0);
+
+        Thread::spawn(move|| {
+            for _ in range(0, AMT * NTHREADS) {
+                assert_eq!(rx.recv().unwrap(), 1);
+            }
+            match rx.try_recv() {
+                Ok(..) => panic!(),
+                _ => {}
+            }
+            dtx.send(()).unwrap();
+        }).detach();
+
+        for _ in range(0, NTHREADS) {
+            let tx = tx.clone();
+            Thread::spawn(move|| {
+                for _ in range(0, AMT) { tx.send(1).unwrap(); }
+            }).detach();
+        }
+        drop(tx);
+        drx.recv().unwrap();
+    }
+
+    #[test]
+    fn oneshot_single_thread_close_port_first() {
+        // Simple test of closing without sending
+        let (_tx, rx) = sync_channel::<int>(0);
+        drop(rx);
+    }
+
+    #[test]
+    fn oneshot_single_thread_close_chan_first() {
+        // Simple test of closing without sending
+        let (tx, _rx) = sync_channel::<int>(0);
+        drop(tx);
+    }
+
+    #[test]
+    fn oneshot_single_thread_send_port_close() {
+        // Testing that the sender cleans up the payload if receiver is closed
+        let (tx, rx) = sync_channel::<Box<int>>(0);
+        drop(rx);
+        assert!(tx.send(box 0).is_err());
+    }
+
+    #[test]
+    fn oneshot_single_thread_recv_chan_close() {
+        // Receiving on a closed chan will panic
+        let res = Thread::spawn(move|| {
+            let (tx, rx) = sync_channel::<int>(0);
+            drop(tx);
+            rx.recv().unwrap();
+        }).join();
+        // What is our res?
+        assert!(res.is_err());
+    }
+
+    #[test]
+    fn oneshot_single_thread_send_then_recv() {
+        let (tx, rx) = sync_channel::<Box<int>>(1);
+        tx.send(box 10).unwrap();
+        assert!(rx.recv().unwrap() == box 10);
+    }
+
+    #[test]
+    fn oneshot_single_thread_try_send_open() {
+        let (tx, rx) = sync_channel::<int>(1);
+        assert_eq!(tx.try_send(10), Ok(()));
+        assert!(rx.recv().unwrap() == 10);
+    }
+
+    #[test]
+    fn oneshot_single_thread_try_send_closed() {
+        let (tx, rx) = sync_channel::<int>(0);
+        drop(rx);
+        assert_eq!(tx.try_send(10), Err(TrySendError::Disconnected(10)));
+    }
+
+    #[test]
+    fn oneshot_single_thread_try_send_closed2() {
+        let (tx, _rx) = sync_channel::<int>(0);
+        assert_eq!(tx.try_send(10), Err(TrySendError::Full(10)));
+    }
+
+    #[test]
+    fn oneshot_single_thread_try_recv_open() {
+        let (tx, rx) = sync_channel::<int>(1);
+        tx.send(10).unwrap();
+        assert!(rx.recv() == Ok(10));
+    }
+
+    #[test]
+    fn oneshot_single_thread_try_recv_closed() {
+        let (tx, rx) = sync_channel::<int>(0);
+        drop(tx);
+        assert!(rx.recv().is_err());
+    }
+
+    #[test]
+    fn oneshot_single_thread_peek_data() {
+        let (tx, rx) = sync_channel::<int>(1);
+        assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
+        tx.send(10).unwrap();
+        assert_eq!(rx.try_recv(), Ok(10));
+    }
+
+    #[test]
+    fn oneshot_single_thread_peek_close() {
+        let (tx, rx) = sync_channel::<int>(0);
+        drop(tx);
+        assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
+        assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
+    }
+
+    #[test]
+    fn oneshot_single_thread_peek_open() {
+        let (_tx, rx) = sync_channel::<int>(0);
+        assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
+    }
+
+    #[test]
+    fn oneshot_multi_task_recv_then_send() {
+        let (tx, rx) = sync_channel::<Box<int>>(0);
+        let _t = Thread::spawn(move|| {
+            assert!(rx.recv().unwrap() == box 10);
+        });
+
+        tx.send(box 10).unwrap();
+    }
+
+    #[test]
+    fn oneshot_multi_task_recv_then_close() {
+        let (tx, rx) = sync_channel::<Box<int>>(0);
+        let _t = Thread::spawn(move|| {
+            drop(tx);
+        });
+        let res = Thread::spawn(move|| {
+            assert!(rx.recv().unwrap() == box 10);
+        }).join();
+        assert!(res.is_err());
+    }
+
+    #[test]
+    fn oneshot_multi_thread_close_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = sync_channel::<int>(0);
+            let _t = Thread::spawn(move|| {
+                drop(rx);
+            });
+            drop(tx);
+        }
+    }
+
+    #[test]
+    fn oneshot_multi_thread_send_close_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = sync_channel::<int>(0);
+            let _t = Thread::spawn(move|| {
+                drop(rx);
+            });
+            let _ = Thread::spawn(move || {
+                tx.send(1).unwrap();
+            }).join();
+        }
+    }
+
+    #[test]
+    fn oneshot_multi_thread_recv_close_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = sync_channel::<int>(0);
+            let _t = Thread::spawn(move|| {
+                let res = Thread::spawn(move|| {
+                    rx.recv().unwrap();
+                }).join();
+                assert!(res.is_err());
+            });
+            let _t = Thread::spawn(move|| {
+                Thread::spawn(move|| {
+                    drop(tx);
+                }).detach();
+            });
+        }
+    }
+
+    #[test]
+    fn oneshot_multi_thread_send_recv_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = sync_channel::<Box<int>>(0);
+            let _t = Thread::spawn(move|| {
+                tx.send(box 10i).unwrap();
+            });
+            assert!(rx.recv().unwrap() == box 10i);
+        }
+    }
+
+    #[test]
+    fn stream_send_recv_stress() {
+        for _ in range(0, stress_factor()) {
+            let (tx, rx) = sync_channel::<Box<int>>(0);
+
+            send(tx, 0);
+            recv(rx, 0);
+
+            fn send(tx: SyncSender<Box<int>>, i: int) {
+                if i == 10 { return }
+
+                Thread::spawn(move|| {
+                    tx.send(box i).unwrap();
+                    send(tx, i + 1);
+                }).detach();
+            }
+
+            fn recv(rx: Receiver<Box<int>>, i: int) {
+                if i == 10 { return }
+
+                Thread::spawn(move|| {
+                    assert!(rx.recv().unwrap() == box i);
+                    recv(rx, i + 1);
+                }).detach();
+            }
+        }
+    }
+
+    #[test]
+    fn recv_a_lot() {
+        // Regression test that we don't run out of stack in scheduler context
+        let (tx, rx) = sync_channel(10000);
+        for _ in range(0u, 10000) { tx.send(()).unwrap(); }
+        for _ in range(0u, 10000) { rx.recv().unwrap(); }
+    }
+
+    #[test]
+    fn shared_chan_stress() {
+        let (tx, rx) = sync_channel(0);
+        let total = stress_factor() + 100;
+        for _ in range(0, total) {
+            let tx = tx.clone();
+            Thread::spawn(move|| {
+                tx.send(()).unwrap();
+            }).detach();
+        }
+
+        for _ in range(0, total) {
+            rx.recv().unwrap();
+        }
+    }
+
+    #[test]
+    fn test_nested_recv_iter() {
+        let (tx, rx) = sync_channel::<int>(0);
+        let (total_tx, total_rx) = sync_channel::<int>(0);
+
+        let _t = Thread::spawn(move|| {
+            let mut acc = 0;
+            for x in rx.iter() {
+                acc += x;
+            }
+            total_tx.send(acc).unwrap();
+        });
+
+        tx.send(3).unwrap();
+        tx.send(1).unwrap();
+        tx.send(2).unwrap();
+        drop(tx);
+        assert_eq!(total_rx.recv().unwrap(), 6);
+    }
+
+    #[test]
+    fn test_recv_iter_break() {
+        let (tx, rx) = sync_channel::<int>(0);
+        let (count_tx, count_rx) = sync_channel(0);
+
+        let _t = Thread::spawn(move|| {
+            let mut count = 0;
+            for x in rx.iter() {
+                if count >= 3 {
+                    break;
+                } else {
+                    count += x;
+                }
+            }
+            count_tx.send(count).unwrap();
+        });
+
+        tx.send(2).unwrap();
+        tx.send(2).unwrap();
+        tx.send(2).unwrap();
+        let _ = tx.try_send(2);
+        drop(tx);
+        assert_eq!(count_rx.recv().unwrap(), 4);
+    }
+
+    #[test]
+    fn try_recv_states() {
+        let (tx1, rx1) = sync_channel::<int>(1);
+        let (tx2, rx2) = sync_channel::<()>(1);
+        let (tx3, rx3) = sync_channel::<()>(1);
+        let _t = Thread::spawn(move|| {
+            rx2.recv().unwrap();
+            tx1.send(1).unwrap();
+            tx3.send(()).unwrap();
+            rx2.recv().unwrap();
+            drop(tx1);
+            tx3.send(()).unwrap();
+        });
+
+        assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty));
+        tx2.send(()).unwrap();
+        rx3.recv().unwrap();
+        assert_eq!(rx1.try_recv(), Ok(1));
+        assert_eq!(rx1.try_recv(), Err(TryRecvError::Empty));
+        tx2.send(()).unwrap();
+        rx3.recv().unwrap();
+        assert_eq!(rx1.try_recv(), Err(TryRecvError::Disconnected));
+    }
+
+    // This bug used to end up in a livelock inside of the Receiver destructor
+    // because the internal state of the Shared packet was corrupted
+    #[test]
+    fn destroy_upgraded_shared_port_when_sender_still_active() {
+        let (tx, rx) = sync_channel::<()>(0);
+        let (tx2, rx2) = sync_channel::<()>(0);
+        let _t = Thread::spawn(move|| {
+            rx.recv().unwrap(); // wait on a oneshot
+            drop(rx);  // destroy a shared
+            tx2.send(()).unwrap();
+        });
+        // make sure the other task has gone to sleep
+        for _ in range(0u, 5000) { Thread::yield_now(); }
+
+        // upgrade to a shared chan and send a message
+        let t = tx.clone();
+        drop(tx);
+        t.send(()).unwrap();
+
+        // wait for the child task to exit before we exit
+        rx2.recv().unwrap();
+    }
+
+    #[test]
+    fn send1() {
+        let (tx, rx) = sync_channel::<int>(0);
+        let _t = Thread::spawn(move|| { rx.recv().unwrap(); });
+        assert_eq!(tx.send(1), Ok(()));
+    }
+
+    #[test]
+    fn send2() {
+        let (tx, rx) = sync_channel::<int>(0);
+        let _t = Thread::spawn(move|| { drop(rx); });
+        assert!(tx.send(1).is_err());
+    }
+
+    #[test]
+    fn send3() {
+        let (tx, rx) = sync_channel::<int>(1);
+        assert_eq!(tx.send(1), Ok(()));
+        let _t =Thread::spawn(move|| { drop(rx); });
+        assert!(tx.send(1).is_err());
+    }
+
+    #[test]
+    fn send4() {
+        let (tx, rx) = sync_channel::<int>(0);
+        let tx2 = tx.clone();
+        let (done, donerx) = channel();
+        let done2 = done.clone();
+        let _t = Thread::spawn(move|| {
+            assert!(tx.send(1).is_err());
+            done.send(()).unwrap();
+        });
+        let _t = Thread::spawn(move|| {
+            assert!(tx2.send(2).is_err());
+            done2.send(()).unwrap();
+        });
+        drop(rx);
+        donerx.recv().unwrap();
+        donerx.recv().unwrap();
+    }
+
+    #[test]
+    fn try_send1() {
+        let (tx, _rx) = sync_channel::<int>(0);
+        assert_eq!(tx.try_send(1), Err(TrySendError::Full(1)));
+    }
+
+    #[test]
+    fn try_send2() {
+        let (tx, _rx) = sync_channel::<int>(1);
+        assert_eq!(tx.try_send(1), Ok(()));
+        assert_eq!(tx.try_send(1), Err(TrySendError::Full(1)));
+    }
+
+    #[test]
+    fn try_send3() {
+        let (tx, rx) = sync_channel::<int>(1);
+        assert_eq!(tx.try_send(1), Ok(()));
+        drop(rx);
+        assert_eq!(tx.try_send(1), Err(TrySendError::Disconnected(1)));
+    }
+
+    #[test]
+    fn issue_15761() {
+        fn repro() {
+            let (tx1, rx1) = sync_channel::<()>(3);
+            let (tx2, rx2) = sync_channel::<()>(3);
+
+            let _t = Thread::spawn(move|| {
+                rx1.recv().unwrap();
+                tx2.try_send(()).unwrap();
+            });
+
+            tx1.try_send(()).unwrap();
+            rx2.recv().unwrap();
+        }
+
+        for _ in range(0u, 100) {
+            repro()
+        }
+    }
+}
diff --git a/src/libstd/sync/mpsc/mpsc_queue.rs b/src/libstd/sync/mpsc/mpsc_queue.rs
new file mode 100644 (file)
index 0000000..8945233
--- /dev/null
@@ -0,0 +1,205 @@
+/* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *
+ *    2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing official
+ * policies, either expressed or implied, of Dmitry Vyukov.
+ */
+
+//! A mostly lock-free multi-producer, single consumer queue.
+//!
+//! This module contains an implementation of a concurrent MPSC queue. This
+//! queue can be used to share data between tasks, and is also used as the
+//! building block of channels in rust.
+//!
+//! Note that the current implementation of this queue has a caveat of the `pop`
+//! method, and see the method for more information about it. Due to this
+//! caveat, this queue may not be appropriate for all use-cases.
+
+#![experimental]
+
+// http://www.1024cores.net/home/lock-free-algorithms
+//                         /queues/non-intrusive-mpsc-node-based-queue
+
+pub use self::PopResult::*;
+
+use core::prelude::*;
+
+use alloc::boxed::Box;
+use core::mem;
+use core::cell::UnsafeCell;
+
+use sync::atomic::{AtomicPtr, Release, Acquire, AcqRel, Relaxed};
+
+/// A result of the `pop` function.
+pub enum PopResult<T> {
+    /// Some data has been popped
+    Data(T),
+    /// The queue is empty
+    Empty,
+    /// The queue is in an inconsistent state. Popping data should succeed, but
+    /// some pushers have yet to make enough progress in order allow a pop to
+    /// succeed. It is recommended that a pop() occur "in the near future" in
+    /// order to see if the sender has made progress or not
+    Inconsistent,
+}
+
+struct Node<T> {
+    next: AtomicPtr<Node<T>>,
+    value: Option<T>,
+}
+
+/// The multi-producer single-consumer structure. This is not cloneable, but it
+/// may be safely shared so long as it is guaranteed that there is only one
+/// popper at a time (many pushers are allowed).
+pub struct Queue<T> {
+    head: AtomicPtr<Node<T>>,
+    tail: UnsafeCell<*mut Node<T>>,
+}
+
+unsafe impl<T:Send> Send for Queue<T> { }
+unsafe impl<T:Send> Sync for Queue<T> { }
+
+impl<T> Node<T> {
+    unsafe fn new(v: Option<T>) -> *mut Node<T> {
+        mem::transmute(box Node {
+            next: AtomicPtr::new(0 as *mut Node<T>),
+            value: v,
+        })
+    }
+}
+
+impl<T: Send> Queue<T> {
+    /// Creates a new queue that is safe to share among multiple producers and
+    /// one consumer.
+    pub fn new() -> Queue<T> {
+        let stub = unsafe { Node::new(None) };
+        Queue {
+            head: AtomicPtr::new(stub),
+            tail: UnsafeCell::new(stub),
+        }
+    }
+
+    /// Pushes a new value onto this queue.
+    pub fn push(&self, t: T) {
+        unsafe {
+            let n = Node::new(Some(t));
+            let prev = self.head.swap(n, AcqRel);
+            (*prev).next.store(n, Release);
+        }
+    }
+
+    /// Pops some data from this queue.
+    ///
+    /// Note that the current implementation means that this function cannot
+    /// return `Option<T>`. It is possible for this queue to be in an
+    /// inconsistent state where many pushes have succeeded and completely
+    /// finished, but pops cannot return `Some(t)`. This inconsistent state
+    /// happens when a pusher is pre-empted at an inopportune moment.
+    ///
+    /// This inconsistent state means that this queue does indeed have data, but
+    /// it does not currently have access to it at this time.
+    pub fn pop(&self) -> PopResult<T> {
+        unsafe {
+            let tail = *self.tail.get();
+            let next = (*tail).next.load(Acquire);
+
+            if !next.is_null() {
+                *self.tail.get() = next;
+                assert!((*tail).value.is_none());
+                assert!((*next).value.is_some());
+                let ret = (*next).value.take().unwrap();
+                let _: Box<Node<T>> = mem::transmute(tail);
+                return Data(ret);
+            }
+
+            if self.head.load(Acquire) == tail {Empty} else {Inconsistent}
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Queue<T> {
+    fn drop(&mut self) {
+        unsafe {
+            let mut cur = *self.tail.get();
+            while !cur.is_null() {
+                let next = (*cur).next.load(Relaxed);
+                let _: Box<Node<T>> = mem::transmute(cur);
+                cur = next;
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::v1::*;
+
+    use sync::mpsc::channel;
+    use super::{Queue, Data, Empty, Inconsistent};
+    use sync::Arc;
+    use thread::Thread;
+
+    #[test]
+    fn test_full() {
+        let q = Queue::new();
+        q.push(box 1i);
+        q.push(box 2i);
+    }
+
+    #[test]
+    fn test() {
+        let nthreads = 8u;
+        let nmsgs = 1000u;
+        let q = Queue::new();
+        match q.pop() {
+            Empty => {}
+            Inconsistent | Data(..) => panic!()
+        }
+        let (tx, rx) = channel();
+        let q = Arc::new(q);
+
+        for _ in range(0, nthreads) {
+            let tx = tx.clone();
+            let q = q.clone();
+            Thread::spawn(move|| {
+                for i in range(0, nmsgs) {
+                    q.push(i);
+                }
+                tx.send(()).unwrap();
+            }).detach();
+        }
+
+        let mut i = 0u;
+        while i < nthreads * nmsgs {
+            match q.pop() {
+                Empty | Inconsistent => {},
+                Data(_) => { i += 1 }
+            }
+        }
+        drop(tx);
+        for _ in range(0, nthreads) {
+            rx.recv().unwrap();
+        }
+    }
+}
diff --git a/src/libstd/sync/mpsc/oneshot.rs b/src/libstd/sync/mpsc/oneshot.rs
new file mode 100644 (file)
index 0000000..5f59975
--- /dev/null
@@ -0,0 +1,375 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// Oneshot channels/ports
+///
+/// This is the initial flavor of channels/ports used for comm module. This is
+/// an optimization for the one-use case of a channel. The major optimization of
+/// this type is to have one and exactly one allocation when the chan/port pair
+/// is created.
+///
+/// Another possible optimization would be to not use an Arc box because
+/// in theory we know when the shared packet can be deallocated (no real need
+/// for the atomic reference counting), but I was having trouble how to destroy
+/// the data early in a drop of a Port.
+///
+/// # Implementation
+///
+/// Oneshots are implemented around one atomic uint variable. This variable
+/// indicates both the state of the port/chan but also contains any tasks
+/// blocked on the port. All atomic operations happen on this one word.
+///
+/// In order to upgrade a oneshot channel, an upgrade is considered a disconnect
+/// on behalf of the channel side of things (it can be mentally thought of as
+/// consuming the port). This upgrade is then also stored in the shared packet.
+/// The one caveat to consider is that when a port sees a disconnected channel
+/// it must check for data because there is no "data plus upgrade" state.
+
+pub use self::Failure::*;
+pub use self::UpgradeResult::*;
+pub use self::SelectionResult::*;
+use self::MyUpgrade::*;
+
+use core::prelude::*;
+
+use sync::mpsc::Receiver;
+use sync::mpsc::blocking::{mod, SignalToken};
+use core::mem;
+use sync::atomic;
+
+// Various states you can find a port in.
+const EMPTY: uint = 0;          // initial state: no data, no blocked reciever
+const DATA: uint = 1;           // data ready for receiver to take
+const DISCONNECTED: uint = 2;   // channel is disconnected OR upgraded
+// Any other value represents a pointer to a SignalToken value. The
+// protocol ensures that when the state moves *to* a pointer,
+// ownership of the token is given to the packet, and when the state
+// moves *from* a pointer, ownership of the token is transferred to
+// whoever changed the state.
+
+pub struct Packet<T> {
+    // Internal state of the chan/port pair (stores the blocked task as well)
+    state: atomic::AtomicUint,
+    // One-shot data slot location
+    data: Option<T>,
+    // when used for the second time, a oneshot channel must be upgraded, and
+    // this contains the slot for the upgrade
+    upgrade: MyUpgrade<T>,
+}
+
+pub enum Failure<T> {
+    Empty,
+    Disconnected,
+    Upgraded(Receiver<T>),
+}
+
+pub enum UpgradeResult {
+    UpSuccess,
+    UpDisconnected,
+    UpWoke(SignalToken),
+}
+
+pub enum SelectionResult<T> {
+    SelCanceled,
+    SelUpgraded(SignalToken, Receiver<T>),
+    SelSuccess,
+}
+
+enum MyUpgrade<T> {
+    NothingSent,
+    SendUsed,
+    GoUp(Receiver<T>),
+}
+
+impl<T: Send> Packet<T> {
+    pub fn new() -> Packet<T> {
+        Packet {
+            data: None,
+            upgrade: NothingSent,
+            state: atomic::AtomicUint::new(EMPTY),
+        }
+    }
+
+    pub fn send(&mut self, t: T) -> Result<(), T> {
+        // Sanity check
+        match self.upgrade {
+            NothingSent => {}
+            _ => panic!("sending on a oneshot that's already sent on "),
+        }
+        assert!(self.data.is_none());
+        self.data = Some(t);
+        self.upgrade = SendUsed;
+
+        match self.state.swap(DATA, atomic::SeqCst) {
+            // Sent the data, no one was waiting
+            EMPTY => Ok(()),
+
+            // Couldn't send the data, the port hung up first. Return the data
+            // back up the stack.
+            DISCONNECTED => {
+                Err(self.data.take().unwrap())
+            }
+
+            // Not possible, these are one-use channels
+            DATA => unreachable!(),
+
+            // There is a thread waiting on the other end. We leave the 'DATA'
+            // state inside so it'll pick it up on the other end.
+            ptr => unsafe {
+                SignalToken::cast_from_uint(ptr).signal();
+                Ok(())
+            }
+        }
+    }
+
+    // Just tests whether this channel has been sent on or not, this is only
+    // safe to use from the sender.
+    pub fn sent(&self) -> bool {
+        match self.upgrade {
+            NothingSent => false,
+            _ => true,
+        }
+    }
+
+    pub fn recv(&mut self) -> Result<T, Failure<T>> {
+        // Attempt to not block the task (it's a little expensive). If it looks
+        // like we're not empty, then immediately go through to `try_recv`.
+        if self.state.load(atomic::SeqCst) == EMPTY {
+            let (wait_token, signal_token) = blocking::tokens();
+            let ptr = unsafe { signal_token.cast_to_uint() };
+
+            // race with senders to enter the blocking state
+            if self.state.compare_and_swap(EMPTY, ptr, atomic::SeqCst) == EMPTY {
+                wait_token.wait();
+                debug_assert!(self.state.load(atomic::SeqCst) != EMPTY);
+            } else {
+                // drop the signal token, since we never blocked
+                drop(unsafe { SignalToken::cast_from_uint(ptr) });
+            }
+        }
+
+        self.try_recv()
+    }
+
+    pub fn try_recv(&mut self) -> Result<T, Failure<T>> {
+        match self.state.load(atomic::SeqCst) {
+            EMPTY => Err(Empty),
+
+            // We saw some data on the channel, but the channel can be used
+            // again to send us an upgrade. As a result, we need to re-insert
+            // into the channel that there's no data available (otherwise we'll
+            // just see DATA next time). This is done as a cmpxchg because if
+            // the state changes under our feet we'd rather just see that state
+            // change.
+            DATA => {
+                self.state.compare_and_swap(DATA, EMPTY, atomic::SeqCst);
+                match self.data.take() {
+                    Some(data) => Ok(data),
+                    None => unreachable!(),
+                }
+            }
+
+            // There's no guarantee that we receive before an upgrade happens,
+            // and an upgrade flags the channel as disconnected, so when we see
+            // this we first need to check if there's data available and *then*
+            // we go through and process the upgrade.
+            DISCONNECTED => {
+                match self.data.take() {
+                    Some(data) => Ok(data),
+                    None => {
+                        match mem::replace(&mut self.upgrade, SendUsed) {
+                            SendUsed | NothingSent => Err(Disconnected),
+                            GoUp(upgrade) => Err(Upgraded(upgrade))
+                        }
+                    }
+                }
+            }
+
+            // We are the sole receiver; there cannot be a blocking
+            // receiver already.
+            _ => unreachable!()
+        }
+    }
+
+    // Returns whether the upgrade was completed. If the upgrade wasn't
+    // completed, then the port couldn't get sent to the other half (it will
+    // never receive it).
+    pub fn upgrade(&mut self, up: Receiver<T>) -> UpgradeResult {
+        let prev = match self.upgrade {
+            NothingSent => NothingSent,
+            SendUsed => SendUsed,
+            _ => panic!("upgrading again"),
+        };
+        self.upgrade = GoUp(up);
+
+        match self.state.swap(DISCONNECTED, atomic::SeqCst) {
+            // If the channel is empty or has data on it, then we're good to go.
+            // Senders will check the data before the upgrade (in case we
+            // plastered over the DATA state).
+            DATA | EMPTY => UpSuccess,
+
+            // If the other end is already disconnected, then we failed the
+            // upgrade. Be sure to trash the port we were given.
+            DISCONNECTED => { self.upgrade = prev; UpDisconnected }
+
+            // If someone's waiting, we gotta wake them up
+            ptr => UpWoke(unsafe { SignalToken::cast_from_uint(ptr) })
+        }
+    }
+
+    pub fn drop_chan(&mut self) {
+        match self.state.swap(DISCONNECTED, atomic::SeqCst) {
+            DATA | DISCONNECTED | EMPTY => {}
+
+            // If someone's waiting, we gotta wake them up
+            ptr => unsafe {
+                SignalToken::cast_from_uint(ptr).signal();
+            }
+        }
+    }
+
+    pub fn drop_port(&mut self) {
+        match self.state.swap(DISCONNECTED, atomic::SeqCst) {
+            // An empty channel has nothing to do, and a remotely disconnected
+            // channel also has nothing to do b/c we're about to run the drop
+            // glue
+            DISCONNECTED | EMPTY => {}
+
+            // There's data on the channel, so make sure we destroy it promptly.
+            // This is why not using an arc is a little difficult (need the box
+            // to stay valid while we take the data).
+            DATA => { self.data.take().unwrap(); }
+
+            // We're the only ones that can block on this port
+            _ => unreachable!()
+        }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // 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(&mut self) -> Result<bool, Receiver<T>> {
+        match self.state.load(atomic::SeqCst) {
+            EMPTY => Ok(false), // Welp, we tried
+            DATA => Ok(true),   // we have some un-acquired data
+            DISCONNECTED if self.data.is_some() => Ok(true), // we have data
+            DISCONNECTED => {
+                match mem::replace(&mut self.upgrade, 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 => { self.upgrade = 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(&mut self, token: SignalToken) -> SelectionResult<T> {
+        let ptr = unsafe { token.cast_to_uint() };
+        match self.state.compare_and_swap(EMPTY, ptr, atomic::SeqCst) {
+            EMPTY => SelSuccess,
+            DATA => {
+                drop(unsafe { SignalToken::cast_from_uint(ptr) });
+                SelCanceled
+            }
+            DISCONNECTED if self.data.is_some() => {
+                drop(unsafe { SignalToken::cast_from_uint(ptr) });
+                SelCanceled
+            }
+            DISCONNECTED => {
+                match mem::replace(&mut self.upgrade, SendUsed) {
+                    // The other end sent us an upgrade, so we need to
+                    // propagate upwards whether the upgrade can receive
+                    // data
+                    GoUp(upgrade) => {
+                        SelUpgraded(unsafe { SignalToken::cast_from_uint(ptr) }, upgrade)
+                    }
+
+                    // If the other end disconnected without sending an
+                    // upgrade, then we have data to receive (the channel is
+                    // disconnected).
+                    up => {
+                        self.upgrade = up;
+                        drop(unsafe { SignalToken::cast_from_uint(ptr) });
+                        SelCanceled
+                    }
+                }
+            }
+            _ => unreachable!(), // we're the "one blocker"
+        }
+    }
+
+    // Remove a previous selecting task from this port. This ensures that the
+    // blocked task will no longer be visible to any other threads.
+    //
+    // The return value indicates whether there's data on this port.
+    pub fn abort_selection(&mut self) -> Result<bool, Receiver<T>> {
+        let state = match self.state.load(atomic::SeqCst) {
+            // Each of these states means that no further activity will happen
+            // with regard to abortion selection
+            s @ EMPTY |
+            s @ DATA |
+            s @ DISCONNECTED => s,
+
+            // If we've got a blocked task, then use an atomic to gain ownership
+            // of it (may fail)
+            ptr => self.state.compare_and_swap(ptr, EMPTY, atomic::SeqCst)
+        };
+
+        // Now that we've got ownership of our state, figure out what to do
+        // about it.
+        match state {
+            EMPTY => unreachable!(),
+            // our task used for select was stolen
+            DATA => Ok(true),
+
+            // If the other end has hung up, then we have complete ownership
+            // of the port. First, check if there was data waiting for us. This
+            // is possible if the other end sent something and then hung up.
+            //
+            // We then need to check to see if there was an upgrade requested,
+            // and if so, the upgraded port needs to have its selection aborted.
+            DISCONNECTED => {
+                if self.data.is_some() {
+                    Ok(true)
+                } else {
+                    match mem::replace(&mut self.upgrade, SendUsed) {
+                        GoUp(port) => Err(port),
+                        _ => Ok(true),
+                    }
+                }
+            }
+
+            // We woke ourselves up from select.
+            ptr => unsafe {
+                drop(SignalToken::cast_from_uint(ptr));
+                Ok(false)
+            }
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Packet<T> {
+    fn drop(&mut self) {
+        assert_eq!(self.state.load(atomic::SeqCst), DISCONNECTED);
+    }
+}
diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs
new file mode 100644 (file)
index 0000000..fc1e0b3
--- /dev/null
@@ -0,0 +1,747 @@
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! 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.
+//!
+//! # Example
+//!
+//! ```rust
+//! use std::sync::mpsc::channel;
+//!
+//! let (tx1, rx1) = channel();
+//! let (tx2, rx2) = channel();
+//!
+//! tx1.send(1i).unwrap();
+//! tx2.send(2i).unwrap();
+//!
+//! select! {
+//!     val = rx1.recv() => {
+//!         assert_eq!(val.unwrap(), 1i);
+//!     },
+//!     val = rx2.recv() => {
+//!         assert_eq!(val.unwrap(), 2i);
+//!     }
+//! }
+//! ```
+
+#![allow(dead_code)]
+#![experimental = "This implementation, while likely sufficient, is unsafe and \
+                   likely to be error prone. At some point in the future this \
+                   module will likely be replaced, and it is currently \
+                   unknown how much API breakage that will cause. The ability \
+                   to select over a number of channels will remain forever, \
+                   but no guarantees beyond this are being made"]
+
+
+use core::prelude::*;
+
+use core::cell::Cell;
+use core::kinds::marker;
+use core::mem;
+use core::uint;
+
+use sync::mpsc::{Receiver, RecvError};
+use sync::mpsc::blocking::{mod, 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 {
+    head: *mut Handle<'static, ()>,
+    tail: *mut Handle<'static, ()>,
+    next_id: Cell<uint>,
+    marker1: marker::NoSend,
+}
+
+/// 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:'rx> {
+    /// The ID of this handle, used to compare against the return value of
+    /// `Select::wait()`
+    id: uint,
+    selector: &'rx Select,
+    next: *mut Handle<'static, ()>,
+    prev: *mut Handle<'static, ()>,
+    added: bool,
+    packet: &'rx (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)]
+#[deriving(PartialEq)]
+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 and
+    /// `wait` will panic!() if called.
+    ///
+    /// Usage of this struct directly can sometimes be burdensome, and usage is
+    /// rather much easier through the `select!` macro.
+    pub fn new() -> Select {
+        Select {
+            marker1: marker::NoSend,
+            head: 0 as *mut Handle<'static, ()>,
+            tail: 0 as *mut Handle<'static, ()>,
+            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: id,
+            selector: self,
+            next: 0 as *mut Handle<'static, ()>,
+            prev: 0 as *mut Handle<'static, ()>,
+            added: false,
+            rx: 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) -> uint {
+        self.wait2(true)
+    }
+
+    /// Helper method for skipping the preflight checks during testing
+    fn wait2(&self, do_preflight_checks: bool) -> uint {
+        // 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 task. 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 = uint::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 != uint::MAX);
+            return ready_id;
+        }
+    }
+
+    fn iter(&self) -> Packets { Packets { cur: self.head } }
+}
+
+impl<'rx, T: Send> Handle<'rx, T> {
+    /// Retrieve the id of this handle.
+    #[inline]
+    pub fn id(&self) -> uint { self.id }
+
+    /// Block 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 Select = mem::transmute(&*self.selector);
+        let me: *mut Handle<'static, ()> = mem::transmute(&*self);
+
+        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 Select = mem::transmute(&*self.selector);
+        let me: *mut Handle<'static, ()> = mem::transmute(&*self);
+
+        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 = 0 as *mut Handle<'static, ()>;
+        self.prev = 0 as *mut Handle<'static, ()>;
+
+        self.added = false;
+    }
+}
+
+#[unsafe_destructor]
+impl Drop for Select {
+    fn drop(&mut self) {
+        assert!(self.head.is_null());
+        assert!(self.tail.is_null());
+    }
+}
+
+#[unsafe_destructor]
+impl<'rx, T: Send> Drop for Handle<'rx, T> {
+    fn drop(&mut self) {
+        unsafe { self.remove() }
+    }
+}
+
+impl Iterator<*mut Handle<'static, ()>> for Packets {
+    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
+        }
+    }
+}
+
+#[cfg(test)]
+#[allow(unused_imports)]
+mod test {
+    use prelude::v1::*;
+
+    use thread::Thread;
+    use super::*;
+    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::<int>();
+        let (tx2, rx2) = channel::<int>();
+        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::<int>();
+        let (_tx2, rx2) = channel::<int>();
+        let (_tx3, rx3) = channel::<int>();
+        let (_tx4, rx4) = channel::<int>();
+        let (tx5, rx5) = channel::<int>();
+        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::<int>();
+        let (tx2, rx2) = channel::<int>();
+        drop(tx2);
+
+        select! {
+            _a1 = rx1.recv() => { panic!() },
+            a2 = rx2.recv() => { assert!(a2.is_err()); }
+        }
+    }
+
+    #[test]
+    fn unblocks() {
+        let (tx1, rx1) = channel::<int>();
+        let (_tx2, rx2) = channel::<int>();
+        let (tx3, rx3) = channel::<int>();
+
+        let _t = Thread::spawn(move|| {
+            for _ in range(0u, 20) { Thread::yield_now(); }
+            tx1.send(1).unwrap();
+            rx3.recv().unwrap();
+            for _ in range(0u, 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::<int>();
+        let (tx2, rx2) = channel::<int>();
+        let (tx3, rx3) = channel::<()>();
+
+        let _t = Thread::spawn(move|| {
+            for _ in range(0u, 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() {
+        static AMT: int = 10000;
+        let (tx1, rx1) = channel::<int>();
+        let (tx2, rx2) = channel::<int>();
+        let (tx3, rx3) = channel::<()>();
+
+        let _t = Thread::spawn(move|| {
+            for i in range(0, AMT) {
+                if i % 2 == 0 {
+                    tx1.send(i).unwrap();
+                } else {
+                    tx2.send(i).unwrap();
+                }
+                rx3.recv().unwrap();
+            }
+        });
+
+        for i in range(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();
+        }
+    }
+
+    #[test]
+    fn cloning() {
+        let (tx1, rx1) = channel::<int>();
+        let (_tx2, rx2) = channel::<int>();
+        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 cloning2() {
+        let (tx1, rx1) = channel::<int>();
+        let (_tx2, rx2) = channel::<int>();
+        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 range(0u, 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 range(0u, 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 range(0u, 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 range(0u, 100) { Thread::yield_now() }
+        tx1.send(()).unwrap();
+        rx2.recv().unwrap();
+    }
+
+    #[test]
+    fn sync1() {
+        let (tx, rx) = sync_channel::<int>(1);
+        tx.send(1).unwrap();
+        select! {
+            n = rx.recv() => { assert_eq!(n.unwrap(), 1); }
+        }
+    }
+
+    #[test]
+    fn sync2() {
+        let (tx, rx) = sync_channel::<int>(0);
+        let _t = Thread::spawn(move|| {
+            for _ in range(0u, 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::<int>(0);
+        let (tx2, rx2): (Sender<int>, Receiver<int>) = 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
new file mode 100644 (file)
index 0000000..e1606cb
--- /dev/null
@@ -0,0 +1,486 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// 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
+/// channels are cloneable allowing for multiple senders.
+///
+/// High level implementation details can be found in the comment of the parent
+/// module. You'll also note that the implementation of the shared and stream
+/// channels are quite similar, and this is no coincidence!
+
+pub use self::Failure::*;
+
+use core::prelude::*;
+
+use core::cmp;
+use core::int;
+
+use sync::{atomic, Mutex, MutexGuard};
+use sync::mpsc::mpsc_queue as mpsc;
+use sync::mpsc::blocking::{mod, SignalToken};
+use sync::mpsc::select::StartResult;
+use sync::mpsc::select::StartResult::*;
+use thread::Thread;
+
+const DISCONNECTED: int = int::MIN;
+const FUDGE: int = 1024;
+#[cfg(test)]
+const MAX_STEALS: int = 5;
+#[cfg(not(test))]
+const MAX_STEALS: int = 1 << 20;
+
+pub struct Packet<T> {
+    queue: mpsc::Queue<T>,
+    cnt: atomic::AtomicInt, // How many items are on this channel
+    steals: int, // How many times has a port received without blocking?
+    to_wake: atomic::AtomicUint, // SignalToken for wake up
+
+    // The number of channels which are currently using this packet.
+    channels: atomic::AtomicInt,
+
+    // See the discussion in Port::drop and the channel send methods for what
+    // these are used for
+    port_dropped: atomic::AtomicBool,
+    sender_drain: atomic::AtomicInt,
+
+    // this lock protects various portions of this implementation during
+    // select()
+    select_lock: Mutex<()>,
+}
+
+pub enum Failure {
+    Empty,
+    Disconnected,
+}
+
+impl<T: Send> Packet<T> {
+    // Creation of a packet *must* be followed by a call to postinit_lock
+    // and later by inherit_blocker
+    pub fn new() -> Packet<T> {
+        let p = Packet {
+            queue: mpsc::Queue::new(),
+            cnt: atomic::AtomicInt::new(0),
+            steals: 0,
+            to_wake: atomic::AtomicUint::new(0),
+            channels: atomic::AtomicInt::new(2),
+            port_dropped: atomic::AtomicBool::new(false),
+            sender_drain: atomic::AtomicInt::new(0),
+            select_lock: Mutex::new(()),
+        };
+        return p;
+    }
+
+    // This function should be used after newly created Packet
+    // was wrapped with an Arc
+    // 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<()> {
+        self.select_lock.lock()
+    }
+
+    // This function is used at the creation of a shared packet to inherit a
+    // previously blocked task. This is done to prevent spurious wakeups of
+    // tasks in select().
+    //
+    // This can only be called at channel-creation time
+    pub fn inherit_blocker(&mut self,
+                           token: Option<SignalToken>,
+                           guard: MutexGuard<()>) {
+        token.map(|token| {
+            assert_eq!(self.cnt.load(atomic::SeqCst), 0);
+            assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+            self.to_wake.store(unsafe { token.cast_to_uint() }, atomic::SeqCst);
+            self.cnt.store(-1, atomic::SeqCst);
+
+            // This store is a little sketchy. What's happening here is that
+            // we're transferring a blocker from a oneshot or stream channel to
+            // this shared channel. In doing so, we never spuriously wake them
+            // up and rather only wake them up at the appropriate time. This
+            // implementation of shared channels assumes that any blocking
+            // recv() will undo the increment of steals performed in try_recv()
+            // once the recv is complete.  This thread that we're inheriting,
+            // however, is not in the middle of recv. Hence, the first time we
+            // wake them up, they're going to wake up from their old port, move
+            // on to the upgraded port, and then call the block recv() function.
+            //
+            // When calling this function, they'll find there's data immediately
+            // available, counting it as a steal. This in fact wasn't a steal
+            // because we appropriately blocked them waiting for data.
+            //
+            // To offset this bad increment, we initially set the steal count to
+            // -1. You'll find some special code in abort_selection() as well to
+            // ensure that this -1 steal count doesn't escape too far.
+            self.steals = -1;
+        });
+
+        // When the shared packet is constructed, we grabbed this lock. The
+        // purpose of this lock is to ensure that abort_selection() doesn't
+        // interfere with this method. After we unlock this lock, we're
+        // signifying that we're done modifying self.cnt and self.to_wake and
+        // the port is ready for the world to continue using it.
+        drop(guard);
+    }
+
+    pub fn send(&mut self, t: T) -> Result<(), T> {
+        // See Port::drop for what's going on
+        if self.port_dropped.load(atomic::SeqCst) { return Err(t) }
+
+        // Note that the multiple sender case is a little trickier
+        // semantically than the single sender case. The logic for
+        // incrementing is "add and if disconnected store disconnected".
+        // This could end up leading some senders to believe that there
+        // wasn't a disconnect if in fact there was a disconnect. This means
+        // that while one thread is attempting to re-store the disconnected
+        // states, other threads could walk through merrily incrementing
+        // this very-negative disconnected count. To prevent senders from
+        // spuriously attempting to send when the channels is actually
+        // disconnected, the count has a ranged check here.
+        //
+        // This is also done for another reason. Remember that the return
+        // value of this function is:
+        //
+        //  `true` == the data *may* be received, this essentially has no
+        //            meaning
+        //  `false` == the data will *never* be received, this has a lot of
+        //             meaning
+        //
+        // In the SPSC case, we have a check of 'queue.is_empty()' to see
+        // whether the data was actually received, but this same condition
+        // means nothing in a multi-producer context. As a result, this
+        // preflight check serves as the definitive "this will never be
+        // received". Once we get beyond this check, we have permanently
+        // entered the realm of "this may be received"
+        if self.cnt.load(atomic::SeqCst) < DISCONNECTED + FUDGE {
+            return Err(t)
+        }
+
+        self.queue.push(t);
+        match self.cnt.fetch_add(1, atomic::SeqCst) {
+            -1 => {
+                self.take_to_wake().signal();
+            }
+
+            // In this case, we have possibly failed to send our data, and
+            // we need to consider re-popping the data in order to fully
+            // destroy it. We must arbitrate among the multiple senders,
+            // however, because the queues that we're using are
+            // single-consumer queues. In order to do this, all exiting
+            // pushers will use an atomic count in order to count those
+            // flowing through. Pushers who see 0 are required to drain as
+            // much as possible, and then can only exit when they are the
+            // only pusher (otherwise they must try again).
+            n if n < DISCONNECTED + FUDGE => {
+                // see the comment in 'try' for a shared channel for why this
+                // window of "not disconnected" is ok.
+                self.cnt.store(DISCONNECTED, atomic::SeqCst);
+
+                if self.sender_drain.fetch_add(1, atomic::SeqCst) == 0 {
+                    loop {
+                        // drain the queue, for info on the thread yield see the
+                        // discussion in try_recv
+                        loop {
+                            match self.queue.pop() {
+                                mpsc::Data(..) => {}
+                                mpsc::Empty => break,
+                                mpsc::Inconsistent => Thread::yield_now(),
+                            }
+                        }
+                        // maybe we're done, if we're not the last ones
+                        // here, then we need to go try again.
+                        if self.sender_drain.fetch_sub(1, atomic::SeqCst) == 1 {
+                            break
+                        }
+                    }
+
+                    // At this point, there may still be data on the queue,
+                    // but only if the count hasn't been incremented and
+                    // some other sender hasn't finished pushing data just
+                    // yet. That sender in question will drain its own data.
+                }
+            }
+
+            // Can't make any assumptions about this case like in the SPSC case.
+            _ => {}
+        }
+
+        Ok(())
+    }
+
+    pub fn recv(&mut self) -> Result<T, Failure> {
+        // This code is essentially the exact same as that found in the stream
+        // case (see stream.rs)
+        match self.try_recv() {
+            Err(Empty) => {}
+            data => return data,
+        }
+
+        let (wait_token, signal_token) = blocking::tokens();
+        if self.decrement(signal_token) == Installed {
+            wait_token.wait()
+        }
+
+        match self.try_recv() {
+            data @ Ok(..) => { self.steals -= 1; data }
+            data => data,
+        }
+    }
+
+    // Essentially the exact same thing as the stream decrement function.
+    // Returns true if blocking should proceed.
+    fn decrement(&mut self, token: SignalToken) -> StartResult {
+        assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+        let ptr = unsafe { token.cast_to_uint() };
+        self.to_wake.store(ptr, atomic::SeqCst);
+
+        let steals = self.steals;
+        self.steals = 0;
+
+        match self.cnt.fetch_sub(1 + steals, atomic::SeqCst) {
+            DISCONNECTED => { self.cnt.store(DISCONNECTED, atomic::SeqCst); }
+            // If we factor in our steals and notice that the channel has no
+            // data, we successfully sleep
+            n => {
+                assert!(n >= 0);
+                if n - steals <= 0 { return Installed }
+            }
+        }
+
+        self.to_wake.store(0, atomic::SeqCst);
+        drop(unsafe { SignalToken::cast_from_uint(ptr) });
+        Abort
+    }
+
+    pub fn try_recv(&mut self) -> Result<T, Failure> {
+        let ret = match self.queue.pop() {
+            mpsc::Data(t) => Some(t),
+            mpsc::Empty => None,
+
+            // This is a bit of an interesting case. The channel is reported as
+            // having data available, but our pop() has failed due to the queue
+            // being in an inconsistent state.  This means that there is some
+            // pusher somewhere which has yet to complete, but we are guaranteed
+            // that a pop will eventually succeed. In this case, we spin in a
+            // yield loop because the remote sender should finish their enqueue
+            // operation "very quickly".
+            //
+            // Avoiding this yield loop would require a different queue
+            // abstraction which provides the guarantee that after M pushes have
+            // succeeded, at least M pops will succeed. The current queues
+            // guarantee that if there are N active pushes, you can pop N times
+            // once all N have finished.
+            mpsc::Inconsistent => {
+                let data;
+                loop {
+                    Thread::yield_now();
+                    match self.queue.pop() {
+                        mpsc::Data(t) => { data = t; break }
+                        mpsc::Empty => panic!("inconsistent => empty"),
+                        mpsc::Inconsistent => {}
+                    }
+                }
+                Some(data)
+            }
+        };
+        match ret {
+            // See the discussion in the stream implementation for why we
+            // might decrement steals.
+            Some(data) => {
+                if self.steals > MAX_STEALS {
+                    match self.cnt.swap(0, atomic::SeqCst) {
+                        DISCONNECTED => {
+                            self.cnt.store(DISCONNECTED, atomic::SeqCst);
+                        }
+                        n => {
+                            let m = cmp::min(n, self.steals);
+                            self.steals -= m;
+                            self.bump(n - m);
+                        }
+                    }
+                    assert!(self.steals >= 0);
+                }
+                self.steals += 1;
+                Ok(data)
+            }
+
+            // See the discussion in the stream implementation for why we try
+            // again.
+            None => {
+                match self.cnt.load(atomic::SeqCst) {
+                    n if n != DISCONNECTED => Err(Empty),
+                    _ => {
+                        match self.queue.pop() {
+                            mpsc::Data(t) => Ok(t),
+                            mpsc::Empty => Err(Disconnected),
+                            // with no senders, an inconsistency is impossible.
+                            mpsc::Inconsistent => unreachable!(),
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // Prepares this shared packet for a channel clone, essentially just bumping
+    // a refcount.
+    pub fn clone_chan(&mut self) {
+        self.channels.fetch_add(1, atomic::SeqCst);
+    }
+
+    // Decrement the reference count on a channel. This is called whenever a
+    // Chan is dropped and may end up waking up a receiver. It's the receiver's
+    // responsibility on the other end to figure out that we've disconnected.
+    pub fn drop_chan(&mut self) {
+        match self.channels.fetch_sub(1, atomic::SeqCst) {
+            1 => {}
+            n if n > 1 => return,
+            n => panic!("bad number of channels left {}", n),
+        }
+
+        match self.cnt.swap(DISCONNECTED, atomic::SeqCst) {
+            -1 => { self.take_to_wake().signal(); }
+            DISCONNECTED => {}
+            n => { assert!(n >= 0); }
+        }
+    }
+
+    // See the long discussion inside of stream.rs for why the queue is drained,
+    // and why it is done in this fashion.
+    pub fn drop_port(&mut self) {
+        self.port_dropped.store(true, atomic::SeqCst);
+        let mut steals = self.steals;
+        while {
+            let cnt = self.cnt.compare_and_swap(steals, DISCONNECTED, atomic::SeqCst);
+            cnt != DISCONNECTED && cnt != steals
+        } {
+            // See the discussion in 'try_recv' for why we yield
+            // control of this thread.
+            loop {
+                match self.queue.pop() {
+                    mpsc::Data(..) => { steals += 1; }
+                    mpsc::Empty | mpsc::Inconsistent => break,
+                }
+            }
+        }
+    }
+
+    // Consumes ownership of the 'to_wake' field.
+    fn take_to_wake(&mut self) -> SignalToken {
+        let ptr = self.to_wake.load(atomic::SeqCst);
+        self.to_wake.store(0, atomic::SeqCst);
+        assert!(ptr != 0);
+        unsafe { SignalToken::cast_from_uint(ptr) }
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // 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(&mut self) -> bool {
+        let cnt = self.cnt.load(atomic::SeqCst);
+        cnt == DISCONNECTED || cnt - self.steals > 0
+    }
+
+    // increment the count on the channel (used for selection)
+    fn bump(&mut self, amt: int) -> int {
+        match self.cnt.fetch_add(amt, atomic::SeqCst) {
+            DISCONNECTED => {
+                self.cnt.store(DISCONNECTED, atomic::SeqCst);
+                DISCONNECTED
+            }
+            n => n
+        }
+    }
+
+    // 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(&mut 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 task waiting on this port, returning whether there's
+    // data on the port.
+    //
+    // This is similar to the stream implementation (hence fewer comments), but
+    // uses a different value for the "steals" variable.
+    pub fn abort_selection(&mut self, _was_upgrade: bool) -> bool {
+        // Before we do anything else, we bounce on this lock. The reason for
+        // doing this is to ensure that any upgrade-in-progress is gone and
+        // done with. Without this bounce, we can race with inherit_blocker
+        // about looking at and dealing with to_wake. Once we have acquired the
+        // lock, we are guaranteed that inherit_blocker is done.
+        {
+            let _guard = self.select_lock.lock();
+        }
+
+        // Like the stream implementation, we want to make sure that the count
+        // on the channel goes non-negative. We don't know how negative the
+        // stream currently is, so instead of using a steal value of 1, we load
+        // the channel count and figure out what we should do to make it
+        // positive.
+        let steals = {
+            let cnt = self.cnt.load(atomic::SeqCst);
+            if cnt < 0 && cnt != DISCONNECTED {-cnt} else {0}
+        };
+        let prev = self.bump(steals + 1);
+
+        if prev == DISCONNECTED {
+            assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+            true
+        } else {
+            let cur = prev + steals + 1;
+            assert!(cur >= 0);
+            if prev < 0 {
+                drop(self.take_to_wake());
+            } else {
+                while self.to_wake.load(atomic::SeqCst) != 0 {
+                    Thread::yield_now();
+                }
+            }
+            // if the number of steals is -1, it was the pre-emptive -1 steal
+            // count from when we inherited a blocker. This is fine because
+            // we're just going to overwrite it with a real value.
+            assert!(self.steals == 0 || self.steals == -1);
+            self.steals = steals;
+            prev >= 0
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Packet<T> {
+    fn drop(&mut self) {
+        // Note that this load is not only an assert for correctness about
+        // disconnection, but also a proper fence before the read of
+        // `to_wake`, so this assert cannot be removed with also removing
+        // the `to_wake` assert.
+        assert_eq!(self.cnt.load(atomic::SeqCst), DISCONNECTED);
+        assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+        assert_eq!(self.channels.load(atomic::SeqCst), 0);
+    }
+}
diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs
new file mode 100644 (file)
index 0000000..1562460
--- /dev/null
@@ -0,0 +1,343 @@
+/* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *    1. Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *
+ *    2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation are
+ * those of the authors and should not be interpreted as representing official
+ * policies, either expressed or implied, of Dmitry Vyukov.
+ */
+
+// http://www.1024cores.net/home/lock-free-algorithms/queues/unbounded-spsc-queue
+
+//! A single-producer single-consumer concurrent queue
+//!
+//! This module contains the implementation of an SPSC queue which can be used
+//! concurrently between two tasks. This data structure is safe to use and
+//! enforces the semantics that there is one pusher and one popper.
+
+#![experimental]
+
+use core::prelude::*;
+
+use alloc::boxed::Box;
+use core::mem;
+use core::cell::UnsafeCell;
+
+use sync::atomic::{AtomicPtr, Relaxed, AtomicUint, Acquire, Release};
+
+// Node within the linked list queue of messages to send
+struct Node<T> {
+    // FIXME: this could be an uninitialized T if we're careful enough, and
+    //      that would reduce memory usage (and be a bit faster).
+    //      is it worth it?
+    value: Option<T>,           // nullable for re-use of nodes
+    next: AtomicPtr<Node<T>>,   // next node in the queue
+}
+
+/// The single-producer single-consumer queue. This structure is not cloneable,
+/// but it can be safely shared in an Arc if it is guaranteed that there
+/// is only one popper and one pusher touching the queue at any one point in
+/// time.
+pub struct Queue<T> {
+    // consumer fields
+    tail: UnsafeCell<*mut Node<T>>, // where to pop from
+    tail_prev: AtomicPtr<Node<T>>, // where to pop from
+
+    // producer fields
+    head: UnsafeCell<*mut Node<T>>,      // where to push to
+    first: UnsafeCell<*mut Node<T>>,     // where to get new nodes from
+    tail_copy: UnsafeCell<*mut Node<T>>, // between first/tail
+
+    // Cache maintenance fields. Additions and subtractions are stored
+    // separately in order to allow them to use nonatomic addition/subtraction.
+    cache_bound: uint,
+    cache_additions: AtomicUint,
+    cache_subtractions: AtomicUint,
+}
+
+unsafe impl<T: Send> Send for Queue<T> { }
+
+unsafe impl<T: Send> Sync for Queue<T> { }
+
+impl<T: Send> Node<T> {
+    fn new() -> *mut Node<T> {
+        unsafe {
+            mem::transmute(box Node {
+                value: None,
+                next: AtomicPtr::new(0 as *mut Node<T>),
+            })
+        }
+    }
+}
+
+impl<T: Send> Queue<T> {
+    /// Creates a new queue.
+    ///
+    /// This is unsafe as the type system doesn't enforce a single
+    /// consumer-producer relationship. It also allows the consumer to `pop`
+    /// items while there is a `peek` active due to all methods having a
+    /// non-mutable receiver.
+    ///
+    /// # Arguments
+    ///
+    ///   * `bound` - This queue implementation is implemented with a linked
+    ///               list, and this means that a push is always a malloc. In
+    ///               order to amortize this cost, an internal cache of nodes is
+    ///               maintained to prevent a malloc from always being
+    ///               necessary. This bound is the limit on the size of the
+    ///               cache (if desired). If the value is 0, then the cache has
+    ///               no bound. Otherwise, the cache will never grow larger than
+    ///               `bound` (although the queue itself could be much larger.
+    pub unsafe fn new(bound: uint) -> Queue<T> {
+        let n1 = Node::new();
+        let n2 = Node::new();
+        (*n1).next.store(n2, Relaxed);
+        Queue {
+            tail: UnsafeCell::new(n2),
+            tail_prev: AtomicPtr::new(n1),
+            head: UnsafeCell::new(n2),
+            first: UnsafeCell::new(n1),
+            tail_copy: UnsafeCell::new(n1),
+            cache_bound: bound,
+            cache_additions: AtomicUint::new(0),
+            cache_subtractions: AtomicUint::new(0),
+        }
+    }
+
+    /// Pushes a new value onto this queue. Note that to use this function
+    /// safely, it must be externally guaranteed that there is only one pusher.
+    pub fn push(&self, t: T) {
+        unsafe {
+            // Acquire a node (which either uses a cached one or allocates a new
+            // one), and then append this to the 'head' node.
+            let n = self.alloc();
+            assert!((*n).value.is_none());
+            (*n).value = Some(t);
+            (*n).next.store(0 as *mut Node<T>, Relaxed);
+            (**self.head.get()).next.store(n, Release);
+            *self.head.get() = n;
+        }
+    }
+
+    unsafe fn alloc(&self) -> *mut Node<T> {
+        // First try to see if we can consume the 'first' node for our uses.
+        // We try to avoid as many atomic instructions as possible here, so
+        // the addition to cache_subtractions is not atomic (plus we're the
+        // only one subtracting from the cache).
+        if *self.first.get() != *self.tail_copy.get() {
+            if self.cache_bound > 0 {
+                let b = self.cache_subtractions.load(Relaxed);
+                self.cache_subtractions.store(b + 1, Relaxed);
+            }
+            let ret = *self.first.get();
+            *self.first.get() = (*ret).next.load(Relaxed);
+            return ret;
+        }
+        // If the above fails, then update our copy of the tail and try
+        // again.
+        *self.tail_copy.get() = self.tail_prev.load(Acquire);
+        if *self.first.get() != *self.tail_copy.get() {
+            if self.cache_bound > 0 {
+                let b = self.cache_subtractions.load(Relaxed);
+                self.cache_subtractions.store(b + 1, Relaxed);
+            }
+            let ret = *self.first.get();
+            *self.first.get() = (*ret).next.load(Relaxed);
+            return ret;
+        }
+        // If all of that fails, then we have to allocate a new node
+        // (there's nothing in the node cache).
+        Node::new()
+    }
+
+    /// Attempts to pop a value from this queue. Remember that to use this type
+    /// safely you must ensure that there is only one popper at a time.
+    pub fn pop(&self) -> Option<T> {
+        unsafe {
+            // The `tail` node is not actually a used node, but rather a
+            // sentinel from where we should start popping from. Hence, look at
+            // tail's next field and see if we can use it. If we do a pop, then
+            // the current tail node is a candidate for going into the cache.
+            let tail = *self.tail.get();
+            let next = (*tail).next.load(Acquire);
+            if next.is_null() { return None }
+            assert!((*next).value.is_some());
+            let ret = (*next).value.take();
+
+            *self.tail.get() = next;
+            if self.cache_bound == 0 {
+                self.tail_prev.store(tail, Release);
+            } else {
+                // FIXME: this is dubious with overflow.
+                let additions = self.cache_additions.load(Relaxed);
+                let subtractions = self.cache_subtractions.load(Relaxed);
+                let size = additions - subtractions;
+
+                if size < self.cache_bound {
+                    self.tail_prev.store(tail, Release);
+                    self.cache_additions.store(additions + 1, Relaxed);
+                } else {
+                    (*self.tail_prev.load(Relaxed)).next.store(next, Relaxed);
+                    // We have successfully erased all references to 'tail', so
+                    // now we can safely drop it.
+                    let _: Box<Node<T>> = mem::transmute(tail);
+                }
+            }
+            return ret;
+        }
+    }
+
+    /// Attempts to peek at the head of the queue, returning `None` if the queue
+    /// has no data currently
+    ///
+    /// # Warning
+    /// The reference returned is invalid if it is not used before the consumer
+    /// pops the value off the queue. If the producer then pushes another value
+    /// onto the queue, it will overwrite the value pointed to by the reference.
+    pub fn peek<'a>(&'a self) -> Option<&'a mut T> {
+        // This is essentially the same as above with all the popping bits
+        // stripped out.
+        unsafe {
+            let tail = *self.tail.get();
+            let next = (*tail).next.load(Acquire);
+            if next.is_null() { return None }
+            return (*next).value.as_mut();
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Queue<T> {
+    fn drop(&mut self) {
+        unsafe {
+            let mut cur = *self.first.get();
+            while !cur.is_null() {
+                let next = (*cur).next.load(Relaxed);
+                let _n: Box<Node<T>> = mem::transmute(cur);
+                cur = next;
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::v1::*;
+
+    use sync::Arc;
+    use super::Queue;
+    use thread::Thread;
+    use sync::mpsc::channel;
+
+    #[test]
+    fn smoke() {
+        unsafe {
+            let queue = Queue::new(0);
+            queue.push(1i);
+            queue.push(2);
+            assert_eq!(queue.pop(), Some(1i));
+            assert_eq!(queue.pop(), Some(2));
+            assert_eq!(queue.pop(), None);
+            queue.push(3);
+            queue.push(4);
+            assert_eq!(queue.pop(), Some(3));
+            assert_eq!(queue.pop(), Some(4));
+            assert_eq!(queue.pop(), None);
+        }
+    }
+
+    #[test]
+    fn peek() {
+        unsafe {
+            let queue = Queue::new(0);
+            queue.push(vec![1i]);
+
+            // Ensure the borrowchecker works
+            match queue.peek() {
+                Some(vec) => match vec.as_slice() {
+                    // Note that `pop` is not allowed here due to borrow
+                    [1] => {}
+                    _ => return
+                },
+                None => unreachable!()
+            }
+
+            queue.pop();
+        }
+    }
+
+    #[test]
+    fn drop_full() {
+        unsafe {
+            let q = Queue::new(0);
+            q.push(box 1i);
+            q.push(box 2i);
+        }
+    }
+
+    #[test]
+    fn smoke_bound() {
+        unsafe {
+            let q = Queue::new(0);
+            q.push(1i);
+            q.push(2);
+            assert_eq!(q.pop(), Some(1));
+            assert_eq!(q.pop(), Some(2));
+            assert_eq!(q.pop(), None);
+            q.push(3);
+            q.push(4);
+            assert_eq!(q.pop(), Some(3));
+            assert_eq!(q.pop(), Some(4));
+            assert_eq!(q.pop(), None);
+        }
+    }
+
+    #[test]
+    fn stress() {
+        unsafe {
+            stress_bound(0);
+            stress_bound(1);
+        }
+
+        unsafe fn stress_bound(bound: uint) {
+            let q = Arc::new(Queue::new(bound));
+
+            let (tx, rx) = channel();
+            let q2 = q.clone();
+            let _t = Thread::spawn(move|| {
+                for _ in range(0u, 100000) {
+                    loop {
+                        match q2.pop() {
+                            Some(1i) => break,
+                            Some(_) => panic!(),
+                            None => {}
+                        }
+                    }
+                }
+                tx.send(()).unwrap();
+            });
+            for _ in range(0i, 100000) {
+                q.push(1);
+            }
+            rx.recv().unwrap();
+        }
+    }
+}
diff --git a/src/libstd/sync/mpsc/stream.rs b/src/libstd/sync/mpsc/stream.rs
new file mode 100644 (file)
index 0000000..01b7992
--- /dev/null
@@ -0,0 +1,484 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// Stream channels
+///
+/// This is the flavor of channels which are optimized for one sender and one
+/// receiver. The sender will be upgraded to a shared channel if the channel is
+/// cloned.
+///
+/// High level implementation details can be found in the comment of the parent
+/// module.
+
+pub use self::Failure::*;
+pub use self::UpgradeResult::*;
+pub use self::SelectionResult::*;
+use self::Message::*;
+
+use core::prelude::*;
+
+use core::cmp;
+use core::int;
+use thread::Thread;
+
+use sync::mpsc::blocking::{mod, SignalToken};
+use sync::mpsc::spsc_queue as spsc;
+use sync::mpsc::Receiver;
+use sync::atomic;
+
+const DISCONNECTED: int = int::MIN;
+#[cfg(test)]
+const MAX_STEALS: int = 5;
+#[cfg(not(test))]
+const MAX_STEALS: int = 1 << 20;
+
+pub struct Packet<T> {
+    queue: spsc::Queue<Message<T>>, // internal queue for all message
+
+    cnt: atomic::AtomicInt, // How many items are on this channel
+    steals: int, // How many times has a port received without blocking?
+    to_wake: atomic::AtomicUint, // SignalToken for the blocked thread to wake up
+
+    port_dropped: atomic::AtomicBool, // flag if the channel has been destroyed.
+}
+
+pub enum Failure<T> {
+    Empty,
+    Disconnected,
+    Upgraded(Receiver<T>),
+}
+
+pub enum UpgradeResult {
+    UpSuccess,
+    UpDisconnected,
+    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> {
+    Data(T),
+    GoUp(Receiver<T>),
+}
+
+impl<T: Send> Packet<T> {
+    pub fn new() -> Packet<T> {
+        Packet {
+            queue: unsafe { spsc::Queue::new(128) },
+
+            cnt: atomic::AtomicInt::new(0),
+            steals: 0,
+            to_wake: atomic::AtomicUint::new(0),
+
+            port_dropped: atomic::AtomicBool::new(false),
+        }
+    }
+
+    pub fn send(&mut self, t: T) -> Result<(), T> {
+        // If the other port has deterministically gone away, then definitely
+        // must return the data back up the stack. Otherwise, the data is
+        // considered as being sent.
+        if self.port_dropped.load(atomic::SeqCst) { return Err(t) }
+
+        match self.do_send(Data(t)) {
+            UpSuccess | UpDisconnected => {},
+            UpWoke(token) => { token.signal(); }
+        }
+        Ok(())
+    }
+
+    pub fn upgrade(&mut self, up: Receiver<T>) -> UpgradeResult {
+        // If the port has gone away, then there's no need to proceed any
+        // further.
+        if self.port_dropped.load(atomic::SeqCst) { return UpDisconnected }
+
+        self.do_send(GoUp(up))
+    }
+
+    fn do_send(&mut self, t: Message<T>) -> UpgradeResult {
+        self.queue.push(t);
+        match self.cnt.fetch_add(1, atomic::SeqCst) {
+            // As described in the mod's doc comment, -1 == wakeup
+            -1 => UpWoke(self.take_to_wake()),
+            // As as described before, SPSC queues must be >= -2
+            -2 => UpSuccess,
+
+            // Be sure to preserve the disconnected state, and the return value
+            // in this case is going to be whether our data was received or not.
+            // This manifests itself on whether we have an empty queue or not.
+            //
+            // Primarily, are required to drain the queue here because the port
+            // will never remove this data. We can only have at most one item to
+            // drain (the port drains the rest).
+            DISCONNECTED => {
+                self.cnt.store(DISCONNECTED, atomic::SeqCst);
+                let first = self.queue.pop();
+                let second = self.queue.pop();
+                assert!(second.is_none());
+
+                match first {
+                    Some(..) => UpSuccess,  // we failed to send the data
+                    None => UpDisconnected, // we successfully sent data
+                }
+            }
+
+            // Otherwise we just sent some data on a non-waiting queue, so just
+            // make sure the world is sane and carry on!
+            n => { assert!(n >= 0); UpSuccess }
+        }
+    }
+
+    // Consumes ownership of the 'to_wake' field.
+    fn take_to_wake(&mut self) -> SignalToken {
+        let ptr = self.to_wake.load(atomic::SeqCst);
+        self.to_wake.store(0, atomic::SeqCst);
+        assert!(ptr != 0);
+        unsafe { SignalToken::cast_from_uint(ptr) }
+    }
+
+    // Decrements the count on the channel for a sleeper, returning the sleeper
+    // back if it shouldn't sleep. Note that this is the location where we take
+    // steals into account.
+    fn decrement(&mut self, token: SignalToken) -> Result<(), SignalToken> {
+        assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+        let ptr = unsafe { token.cast_to_uint() };
+        self.to_wake.store(ptr, atomic::SeqCst);
+
+        let steals = self.steals;
+        self.steals = 0;
+
+        match self.cnt.fetch_sub(1 + steals, atomic::SeqCst) {
+            DISCONNECTED => { self.cnt.store(DISCONNECTED, atomic::SeqCst); }
+            // If we factor in our steals and notice that the channel has no
+            // data, we successfully sleep
+            n => {
+                assert!(n >= 0);
+                if n - steals <= 0 { return Ok(()) }
+            }
+        }
+
+        self.to_wake.store(0, atomic::SeqCst);
+        Err(unsafe { SignalToken::cast_from_uint(ptr) })
+    }
+
+    pub fn recv(&mut self) -> Result<T, Failure<T>> {
+        // Optimistic preflight check (scheduling is expensive).
+        match self.try_recv() {
+            Err(Empty) => {}
+            data => return data,
+        }
+
+        // Welp, our channel has no data. Deschedule the current task and
+        // initiate the blocking protocol.
+        let (wait_token, signal_token) = blocking::tokens();
+        if self.decrement(signal_token).is_ok() {
+            wait_token.wait()
+        }
+
+        match self.try_recv() {
+            // Messages which actually popped from the queue shouldn't count as
+            // a steal, so offset the decrement here (we already have our
+            // "steal" factored into the channel count above).
+            data @ Ok(..) |
+            data @ Err(Upgraded(..)) => {
+                self.steals -= 1;
+                data
+            }
+
+            data => data,
+        }
+    }
+
+    pub fn try_recv(&mut self) -> Result<T, Failure<T>> {
+        match self.queue.pop() {
+            // If we stole some data, record to that effect (this will be
+            // factored into cnt later on).
+            //
+            // Note that we don't allow steals to grow without bound in order to
+            // prevent eventual overflow of either steals or cnt as an overflow
+            // would have catastrophic results. Sometimes, steals > cnt, but
+            // other times cnt > steals, so we don't know the relation between
+            // steals and cnt. This code path is executed only rarely, so we do
+            // a pretty slow operation, of swapping 0 into cnt, taking steals
+            // down as much as possible (without going negative), and then
+            // adding back in whatever we couldn't factor into steals.
+            Some(data) => {
+                if self.steals > MAX_STEALS {
+                    match self.cnt.swap(0, atomic::SeqCst) {
+                        DISCONNECTED => {
+                            self.cnt.store(DISCONNECTED, atomic::SeqCst);
+                        }
+                        n => {
+                            let m = cmp::min(n, self.steals);
+                            self.steals -= m;
+                            self.bump(n - m);
+                        }
+                    }
+                    assert!(self.steals >= 0);
+                }
+                self.steals += 1;
+                match data {
+                    Data(t) => Ok(t),
+                    GoUp(up) => Err(Upgraded(up)),
+                }
+            }
+
+            None => {
+                match self.cnt.load(atomic::SeqCst) {
+                    n if n != DISCONNECTED => Err(Empty),
+
+                    // This is a little bit of a tricky case. We failed to pop
+                    // data above, and then we have viewed that the channel is
+                    // disconnected. In this window more data could have been
+                    // sent on the channel. It doesn't really make sense to
+                    // return that the channel is disconnected when there's
+                    // actually data on it, so be extra sure there's no data by
+                    // popping one more time.
+                    //
+                    // We can ignore steals because the other end is
+                    // disconnected and we'll never need to really factor in our
+                    // steals again.
+                    _ => {
+                        match self.queue.pop() {
+                            Some(Data(t)) => Ok(t),
+                            Some(GoUp(up)) => Err(Upgraded(up)),
+                            None => Err(Disconnected),
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    pub fn drop_chan(&mut self) {
+        // Dropping a channel is pretty simple, we just flag it as disconnected
+        // and then wakeup a blocker if there is one.
+        match self.cnt.swap(DISCONNECTED, atomic::SeqCst) {
+            -1 => { self.take_to_wake().signal(); }
+            DISCONNECTED => {}
+            n => { assert!(n >= 0); }
+        }
+    }
+
+    pub fn drop_port(&mut self) {
+        // Dropping a port seems like a fairly trivial thing. In theory all we
+        // need to do is flag that we're disconnected and then everything else
+        // can take over (we don't have anyone to wake up).
+        //
+        // The catch for Ports is that we want to drop the entire contents of
+        // the queue. There are multiple reasons for having this property, the
+        // largest of which is that if another chan is waiting in this channel
+        // (but not received yet), then waiting on that port will cause a
+        // deadlock.
+        //
+        // So if we accept that we must now destroy the entire contents of the
+        // queue, this code may make a bit more sense. The tricky part is that
+        // we can't let any in-flight sends go un-dropped, we have to make sure
+        // *everything* is dropped and nothing new will come onto the channel.
+
+        // The first thing we do is set a flag saying that we're done for. All
+        // sends are gated on this flag, so we're immediately guaranteed that
+        // there are a bounded number of active sends that we'll have to deal
+        // with.
+        self.port_dropped.store(true, atomic::SeqCst);
+
+        // Now that we're guaranteed to deal with a bounded number of senders,
+        // we need to drain the queue. This draining process happens atomically
+        // with respect to the "count" of the channel. If the count is nonzero
+        // (with steals taken into account), then there must be data on the
+        // channel. In this case we drain everything and then try again. We will
+        // continue to fail while active senders send data while we're dropping
+        // data, but eventually we're guaranteed to break out of this loop
+        // (because there is a bounded number of senders).
+        let mut steals = self.steals;
+        while {
+            let cnt = self.cnt.compare_and_swap(
+                            steals, DISCONNECTED, atomic::SeqCst);
+            cnt != DISCONNECTED && cnt != steals
+        } {
+            loop {
+                match self.queue.pop() {
+                    Some(..) => { steals += 1; }
+                    None => break
+                }
+            }
+        }
+
+        // At this point in time, we have gated all future senders from sending,
+        // and we have flagged the channel as being disconnected. The senders
+        // still have some responsibility, however, because some sends may not
+        // complete until after we flag the disconnection. There are more
+        // details in the sending methods that see DISCONNECTED
+    }
+
+    ////////////////////////////////////////////////////////////////////////////
+    // 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(&mut 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(&GoUp(..)) => {
+                match self.recv() {
+                    Err(Upgraded(port)) => Err(port),
+                    _ => unreachable!(),
+                }
+            }
+            Some(..) => Ok(true),
+            None => Ok(false)
+        }
+    }
+
+    // increment the count on the channel (used for selection)
+    fn bump(&mut self, amt: int) -> int {
+        match self.cnt.fetch_add(amt, atomic::SeqCst) {
+            DISCONNECTED => {
+                self.cnt.store(DISCONNECTED, atomic::SeqCst);
+                DISCONNECTED
+            }
+            n => n
+        }
+    }
+
+    // Attempts to start selecting on this port. Like a oneshot, this can fail
+    // immediately because of an upgrade.
+    pub fn start_selection(&mut self, token: SignalToken) -> SelectionResult<T> {
+        match self.decrement(token) {
+            Ok(()) => SelSuccess,
+            Err(token) => {
+                let ret = match self.queue.peek() {
+                    Some(&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);
+                return ret;
+            }
+        }
+    }
+
+    // Removes a previous task from being blocked in this port
+    pub fn abort_selection(&mut self,
+                           was_upgrade: bool) -> Result<bool, Receiver<T>> {
+        // If we're aborting selection after upgrading from a oneshot, then
+        // we're guarantee that no one is waiting. The only way that we could
+        // have seen the upgrade is if data was actually sent on the channel
+        // half again. For us, this means that there is guaranteed to be data on
+        // this channel. Furthermore, we're guaranteed that there was no
+        // start_selection previously, so there's no need to modify `self.cnt`
+        // at all.
+        //
+        // Hence, because of these invariants, we immediately return `Ok(true)`.
+        // Note that the data may not actually be sent on the channel just yet.
+        // The other end could have flagged the upgrade but not sent data to
+        // this end. This is fine because we know it's a small bounded windows
+        // of time until the data is actually sent.
+        if was_upgrade {
+            assert_eq!(self.steals, 0);
+            assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+            return Ok(true)
+        }
+
+        // We want to make sure that the count on the channel goes non-negative,
+        // and in the stream case we can have at most one steal, so just assume
+        // that we had one steal.
+        let steals = 1;
+        let prev = self.bump(steals + 1);
+
+        // If we were previously disconnected, then we know for sure that there
+        // is no task in to_wake, so just keep going
+        let has_data = if prev == DISCONNECTED {
+            assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+            true // there is data, that data is that we're disconnected
+        } else {
+            let cur = prev + steals + 1;
+            assert!(cur >= 0);
+
+            // If the previous count was negative, then we just made things go
+            // positive, hence we passed the -1 boundary and we're responsible
+            // for removing the to_wake() field and trashing it.
+            //
+            // If the previous count was positive then we're in a tougher
+            // situation. A possible race is that a sender just incremented
+            // through -1 (meaning it's going to try to wake a task up), but it
+            // hasn't yet read the to_wake. In order to prevent a future recv()
+            // from waking up too early (this sender picking up the plastered
+            // over to_wake), we spin loop here waiting for to_wake to be 0.
+            // Note that this entire select() implementation needs an overhaul,
+            // and this is *not* the worst part of it, so this is not done as a
+            // final solution but rather out of necessity for now to get
+            // something working.
+            if prev < 0 {
+                drop(self.take_to_wake());
+            } else {
+                while self.to_wake.load(atomic::SeqCst) != 0 {
+                    Thread::yield_now();
+                }
+            }
+            assert_eq!(self.steals, 0);
+            self.steals = steals;
+
+            // if we were previously positive, then there's surely data to
+            // receive
+            prev >= 0
+        };
+
+        // Now that we've determined that this queue "has data", we peek at the
+        // queue to see if the data is an upgrade or not. If it's an upgrade,
+        // then we need to destroy this port and abort selection on the
+        // upgraded port.
+        if has_data {
+            match self.queue.peek() {
+                Some(&GoUp(..)) => {
+                    match self.queue.pop() {
+                        Some(GoUp(port)) => Err(port),
+                        _ => unreachable!(),
+                    }
+                }
+                _ => Ok(true),
+            }
+        } else {
+            Ok(false)
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Packet<T> {
+    fn drop(&mut self) {
+        // Note that this load is not only an assert for correctness about
+        // disconnection, but also a proper fence before the read of
+        // `to_wake`, so this assert cannot be removed with also removing
+        // the `to_wake` assert.
+        assert_eq!(self.cnt.load(atomic::SeqCst), DISCONNECTED);
+        assert_eq!(self.to_wake.load(atomic::SeqCst), 0);
+    }
+}
diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs
new file mode 100644 (file)
index 0000000..2800583
--- /dev/null
@@ -0,0 +1,483 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// Synchronous channels/ports
+///
+/// This channel implementation differs significantly from the asynchronous
+/// implementations found next to it (oneshot/stream/share). This is an
+/// implementation of a synchronous, bounded buffer channel.
+///
+/// Each channel is created with some amount of backing buffer, and sends will
+/// *block* until buffer space becomes available. A buffer size of 0 is valid,
+/// which means that every successful send is paired with a successful recv.
+///
+/// This flavor of channels defines a new `send_opt` method for channels which
+/// is the method by which a message is sent but the task does not panic if it
+/// cannot be delivered.
+///
+/// Another major difference is that send() will *always* return back the data
+/// if it couldn't be sent. This is because it is deterministically known when
+/// the data is received and when it is not received.
+///
+/// Implementation-wise, it can all be summed up with "use a mutex plus some
+/// logic". The mutex used here is an OS native mutex, meaning that no user code
+/// is run inside of the mutex (to prevent context switching). This
+/// implementation shares almost all code for the buffered and unbuffered cases
+/// of a synchronous channel. There are a few branches for the unbuffered case,
+/// but they're mostly just relevant to blocking senders.
+
+use core::prelude::*;
+
+pub use self::Failure::*;
+use self::Blocker::*;
+
+use vec::Vec;
+use core::mem;
+
+use sync::{atomic, Mutex, MutexGuard};
+use sync::mpsc::blocking::{mod, WaitToken, SignalToken};
+use sync::mpsc::select::StartResult::{mod, Installed, Abort};
+
+pub struct Packet<T> {
+    /// Only field outside of the mutex. Just done for kicks, but mainly because
+    /// the other shared channel already had the code implemented
+    channels: atomic::AtomicUint,
+
+    lock: Mutex<State<T>>,
+}
+
+unsafe impl<T:Send> Send for Packet<T> { }
+
+unsafe impl<T:Send> Sync for Packet<T> { }
+
+struct State<T> {
+    disconnected: bool, // Is the channel disconnected yet?
+    queue: Queue,       // queue of senders waiting to send data
+    blocker: Blocker,   // currently blocked task on this channel
+    buf: Buffer<T>,     // storage for buffered messages
+    cap: uint,          // capacity of this channel
+
+    /// A curious flag used to indicate whether a sender failed or succeeded in
+    /// blocking. This is used to transmit information back to the task that it
+    /// must dequeue its message from the buffer because it was not received.
+    /// This is only relevant in the 0-buffer case. This obviously cannot be
+    /// safely constructed, but it's guaranteed to always have a valid pointer
+    /// value.
+    canceled: Option<&'static mut bool>,
+}
+
+unsafe impl<T: Send> Send for State<T> {}
+
+/// Possible flavors of threads who can be blocked on this channel.
+enum Blocker {
+    BlockedSender(SignalToken),
+    BlockedReceiver(SignalToken),
+    NoneBlocked
+}
+
+/// Simple queue for threading tasks together. Nodes are stack-allocated, so
+/// this structure is not safe at all
+struct Queue {
+    head: *mut Node,
+    tail: *mut Node,
+}
+
+struct Node {
+    token: Option<SignalToken>,
+    next: *mut Node,
+}
+
+unsafe impl Send for Node {}
+
+/// A simple ring-buffer
+struct Buffer<T> {
+    buf: Vec<Option<T>>,
+    start: uint,
+    size: uint,
+}
+
+#[deriving(Show)]
+pub enum Failure {
+    Empty,
+    Disconnected,
+}
+
+/// Atomically blocks the current thread, placing it into `slot`, unlocking `lock`
+/// in the meantime. This re-locks the mutex upon returning.
+fn wait<'a, 'b, T: Send>(lock: &'a Mutex<State<T>>,
+                         mut guard: MutexGuard<'b, State<T>>,
+                         f: fn(SignalToken) -> Blocker)
+                         -> MutexGuard<'a, State<T>>
+{
+    let (wait_token, signal_token) = blocking::tokens();
+    match mem::replace(&mut guard.blocker, f(signal_token)) {
+        NoneBlocked => {}
+        _ => unreachable!(),
+    }
+    drop(guard);        // unlock
+    wait_token.wait();  // block
+    lock.lock()         // relock
+}
+
+/// Wakes up a thread, dropping the lock at the correct time
+fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) {
+    // We need to be careful to wake up the waiting task *outside* of the mutex
+    // in case it incurs a context switch.
+    drop(guard);
+    token.signal();
+}
+
+impl<T: Send> Packet<T> {
+    pub fn new(cap: uint) -> Packet<T> {
+        Packet {
+            channels: atomic::AtomicUint::new(1),
+            lock: Mutex::new(State {
+                disconnected: false,
+                blocker: NoneBlocked,
+                cap: cap,
+                canceled: None,
+                queue: Queue {
+                    head: 0 as *mut Node,
+                    tail: 0 as *mut Node,
+                },
+                buf: Buffer {
+                    buf: Vec::from_fn(cap + if cap == 0 {1} else {0}, |_| None),
+                    start: 0,
+                    size: 0,
+                },
+            }),
+        }
+    }
+
+    // wait until a send slot is available, returning locked access to
+    // the channel state.
+    fn acquire_send_slot(&self) -> MutexGuard<State<T>> {
+        let mut node = Node { token: None, next: 0 as *mut Node };
+        loop {
+            let mut guard = self.lock.lock();
+            // are we ready to go?
+            if guard.disconnected || guard.buf.size() < guard.buf.cap() {
+                return guard;
+            }
+            // no room; actually block
+            let wait_token = guard.queue.enqueue(&mut node);
+            drop(guard);
+            wait_token.wait();
+        }
+    }
+
+    pub fn send(&self, t: T) -> Result<(), T> {
+        let mut guard = self.acquire_send_slot();
+        if guard.disconnected { return Err(t) }
+        guard.buf.enqueue(t);
+
+        match mem::replace(&mut guard.blocker, NoneBlocked) {
+            // if our capacity is 0, then we need to wait for a receiver to be
+            // available to take our data. After waiting, we check again to make
+            // sure the port didn't go away in the meantime. If it did, we need
+            // to hand back our data.
+            NoneBlocked if guard.cap == 0 => {
+                let mut canceled = false;
+                assert!(guard.canceled.is_none());
+                guard.canceled = Some(unsafe { mem::transmute(&mut canceled) });
+                let mut guard = wait(&self.lock, guard, BlockedSender);
+                if canceled {Err(guard.buf.dequeue())} else {Ok(())}
+            }
+
+            // success, we buffered some data
+            NoneBlocked => Ok(()),
+
+            // success, someone's about to receive our buffered data.
+            BlockedReceiver(token) => { wakeup(token, guard); Ok(()) }
+
+            BlockedSender(..) => panic!("lolwut"),
+        }
+    }
+
+    pub fn try_send(&self, t: T) -> Result<(), super::TrySendError<T>> {
+        let mut guard = self.lock.lock();
+        if guard.disconnected {
+            Err(super::TrySendError::Disconnected(t))
+        } else if guard.buf.size() == guard.buf.cap() {
+            Err(super::TrySendError::Full(t))
+        } else if guard.cap == 0 {
+            // With capacity 0, even though we have buffer space we can't
+            // transfer the data unless there's a receiver waiting.
+            match mem::replace(&mut guard.blocker, NoneBlocked) {
+                NoneBlocked => Err(super::TrySendError::Full(t)),
+                BlockedSender(..) => unreachable!(),
+                BlockedReceiver(token) => {
+                    guard.buf.enqueue(t);
+                    wakeup(token, guard);
+                    Ok(())
+                }
+            }
+        } else {
+            // 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());
+            guard.buf.enqueue(t);
+            match mem::replace(&mut guard.blocker, NoneBlocked) {
+                BlockedReceiver(token) => wakeup(token, guard),
+                NoneBlocked => {}
+                BlockedSender(..) => unreachable!(),
+            }
+            Ok(())
+        }
+    }
+
+    // Receives a message from this channel
+    //
+    // When reading this, remember that there can only ever be one receiver at
+    // time.
+    pub fn recv(&self) -> Result<T, ()> {
+        let mut guard = self.lock.lock();
+
+        // Wait for the buffer to have something in it. No need for a while loop
+        // because we're the only receiver.
+        let mut waited = false;
+        if !guard.disconnected && guard.buf.size() == 0 {
+            guard = wait(&self.lock, guard, BlockedReceiver);
+            waited = true;
+        }
+        if guard.disconnected && guard.buf.size() == 0 { return Err(()) }
+
+        // Pick up the data, wake up our neighbors, and carry on
+        assert!(guard.buf.size() > 0);
+        let ret = guard.buf.dequeue();
+        self.wakeup_senders(waited, guard);
+        return Ok(ret);
+    }
+
+    pub fn try_recv(&self) -> Result<T, Failure> {
+        let mut guard = self.lock.lock();
+
+        // Easy cases first
+        if guard.disconnected { return Err(Disconnected) }
+        if guard.buf.size() == 0 { return Err(Empty) }
+
+        // Be sure to wake up neighbors
+        let ret = Ok(guard.buf.dequeue());
+        self.wakeup_senders(false, guard);
+
+        return ret;
+    }
+
+    // Wake up pending senders after some data has been received
+    //
+    // * `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>>) {
+        let pending_sender1: Option<SignalToken> = guard.queue.dequeue();
+
+        // If this is a no-buffer channel (cap == 0), then if we didn't wait we
+        // need to ACK the sender. If we waited, then the sender waking us up
+        // was already the ACK.
+        let pending_sender2 = if guard.cap == 0 && !waited {
+            match mem::replace(&mut guard.blocker, NoneBlocked) {
+                NoneBlocked => None,
+                BlockedReceiver(..) => unreachable!(),
+                BlockedSender(token) => {
+                    guard.canceled.take();
+                    Some(token)
+                }
+            }
+        } else {
+            None
+        };
+        mem::drop(guard);
+
+        // only outside of the lock do we wake up the pending tasks
+        pending_sender1.map(|t| t.signal());
+        pending_sender2.map(|t| t.signal());
+    }
+
+    // Prepares this shared packet for a channel clone, essentially just bumping
+    // a refcount.
+    pub fn clone_chan(&self) {
+        self.channels.fetch_add(1, atomic::SeqCst);
+    }
+
+    pub fn drop_chan(&self) {
+        // Only flag the channel as disconnected if we're the last channel
+        match self.channels.fetch_sub(1, atomic::SeqCst) {
+            1 => {}
+            _ => return
+        }
+
+        // Not much to do other than wake up a receiver if one's there
+        let mut guard = self.lock.lock();
+        if guard.disconnected { return }
+        guard.disconnected = true;
+        match mem::replace(&mut guard.blocker, NoneBlocked) {
+            NoneBlocked => {}
+            BlockedSender(..) => unreachable!(),
+            BlockedReceiver(token) => wakeup(token, guard),
+        }
+    }
+
+    pub fn drop_port(&self) {
+        let mut guard = self.lock.lock();
+
+        if guard.disconnected { return }
+        guard.disconnected = true;
+
+        // If the capacity is 0, then the sender may want its data back after
+        // we're disconnected. Otherwise it's now our responsibility to destroy
+        // the buffered data. As with many other portions of this code, this
+        // 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())
+        } else {
+            Vec::new()
+        };
+        let mut queue = mem::replace(&mut guard.queue, Queue {
+            head: 0 as *mut Node,
+            tail: 0 as *mut Node,
+        });
+
+        let waiter = match mem::replace(&mut guard.blocker, NoneBlocked) {
+            NoneBlocked => None,
+            BlockedSender(token) => {
+                *guard.canceled.take().unwrap() = true;
+                Some(token)
+            }
+            BlockedReceiver(..) => unreachable!(),
+        };
+        mem::drop(guard);
+
+        loop {
+            match queue.dequeue() {
+                Some(token) => { token.signal(); }
+                None => break,
+            }
+        }
+        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();
+        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();
+        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 task from this port. This ensures that the
+    // blocked task 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();
+        match mem::replace(&mut guard.blocker, NoneBlocked) {
+            NoneBlocked => true,
+            BlockedSender(token) => {
+                guard.blocker = BlockedSender(token);
+                true
+            }
+            BlockedReceiver(token) => { drop(token); false }
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T: Send> Drop for Packet<T> {
+    fn drop(&mut self) {
+        assert_eq!(self.channels.load(atomic::SeqCst), 0);
+        let mut guard = self.lock.lock();
+        assert!(guard.queue.dequeue().is_none());
+        assert!(guard.canceled.is_none());
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Buffer, a simple ring buffer backed by Vec<T>
+////////////////////////////////////////////////////////////////////////////////
+
+impl<T> Buffer<T> {
+    fn enqueue(&mut self, t: T) {
+        let pos = (self.start + self.size) % self.buf.len();
+        self.size += 1;
+        let prev = mem::replace(&mut self.buf[pos], Some(t));
+        assert!(prev.is_none());
+    }
+
+    fn dequeue(&mut self) -> T {
+        let start = self.start;
+        self.size -= 1;
+        self.start = (self.start + 1) % self.buf.len();
+        self.buf[start].take().unwrap()
+    }
+
+    fn size(&self) -> uint { self.size }
+    fn cap(&self) -> uint { self.buf.len() }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Queue, a simple queue to enqueue tasks with (stack-allocated nodes)
+////////////////////////////////////////////////////////////////////////////////
+
+impl Queue {
+    fn enqueue(&mut self, node: &mut Node) -> WaitToken {
+        let (wait_token, signal_token) = blocking::tokens();
+        node.token = Some(signal_token);
+        node.next = 0 as *mut Node;
+
+        if self.tail.is_null() {
+            self.head = node as *mut Node;
+            self.tail = node as *mut Node;
+        } else {
+            unsafe {
+                (*self.tail).next = node as *mut Node;
+                self.tail = node as *mut Node;
+            }
+        }
+
+        wait_token
+    }
+
+    fn dequeue(&mut self) -> Option<SignalToken> {
+        if self.head.is_null() {
+            return None
+        }
+        let node = self.head;
+        self.head = unsafe { (*node).next };
+        if self.head.is_null() {
+            self.tail = 0 as *mut Node;
+        }
+        unsafe {
+            (*node).next = 0 as *mut Node;
+            Some((*node).token.take().unwrap())
+        }
+    }
+}
index 87a02bd4ef5f5b0106a5c545e39bd2fd46cab802..1562031499fc86f4f736b492c308050be6da907f 100644 (file)
@@ -37,7 +37,7 @@
 /// ```rust
 /// use std::sync::{Arc, Mutex};
 /// use std::thread::Thread;
-/// use std::comm::channel;
+/// use std::sync::mpsc::channel;
 ///
 /// const N: uint = 10;
 ///
 ///         let mut data = data.lock();
 ///         *data += 1;
 ///         if *data == N {
-///             tx.send(());
+///             tx.send(()).unwrap();
 ///         }
 ///         // the lock is unlocked here when `data` goes out of scope.
 ///     }).detach();
 /// }
 ///
-/// rx.recv();
+/// rx.recv().unwrap();
 /// ```
 pub struct Mutex<T> {
     // Note that this static mutex is in a *box*, not inlined into the struct
@@ -284,7 +284,7 @@ fn drop(&mut self) {
 mod test {
     use prelude::v1::*;
 
-    use comm::channel;
+    use sync::mpsc::channel;
     use sync::{Arc, Mutex, StaticMutex, MUTEX_INIT, Condvar};
     use thread::Thread;
 
@@ -329,14 +329,14 @@ fn inc() {
         let (tx, rx) = channel();
         for _ in range(0, K) {
             let tx2 = tx.clone();
-            Thread::spawn(move|| { inc(); tx2.send(()); }).detach();
+            Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); }).detach();
             let tx2 = tx.clone();
-            Thread::spawn(move|| { inc(); tx2.send(()); }).detach();
+            Thread::spawn(move|| { inc(); tx2.send(()).unwrap(); }).detach();
         }
 
         drop(tx);
         for _ in range(0, 2 * K) {
-            rx.recv();
+            rx.recv().unwrap();
         }
         assert_eq!(unsafe {CNT}, J * K * 2);
         unsafe {
@@ -357,7 +357,7 @@ fn test_mutex_arc_condvar() {
         let (tx, rx) = channel();
         let _t = Thread::spawn(move|| {
             // wait until parent gets in
-            rx.recv();
+            rx.recv().unwrap();
             let &(ref lock, ref cvar) = &*packet2.0;
             let mut lock = lock.lock();
             *lock = true;
@@ -366,7 +366,7 @@ fn test_mutex_arc_condvar() {
 
         let &(ref lock, ref cvar) = &*packet.0;
         let lock = lock.lock();
-        tx.send(());
+        tx.send(()).unwrap();
         assert!(!*lock);
         while !*lock {
             cvar.wait(&lock);
@@ -381,7 +381,7 @@ fn test_arc_condvar_poison() {
         let (tx, rx) = channel();
 
         let _t = Thread::spawn(move || -> () {
-            rx.recv();
+            rx.recv().unwrap();
             let &(ref lock, ref cvar) = &*packet2.0;
             let _g = lock.lock();
             cvar.notify_one();
@@ -391,7 +391,7 @@ fn test_arc_condvar_poison() {
 
         let &(ref lock, ref cvar) = &*packet.0;
         let lock = lock.lock();
-        tx.send(());
+        tx.send(()).unwrap();
         while *lock == 1 {
             cvar.wait(&lock);
         }
@@ -421,9 +421,9 @@ fn test_mutex_arc_nested() {
             let lock = arc2.lock();
             let lock2 = lock.lock();
             assert_eq!(*lock2, 1);
-            tx.send(());
+            tx.send(()).unwrap();
         });
-        rx.recv();
+        rx.recv().unwrap();
     }
 
     #[test]
index fe25eca03d7cf6cfa388eee60de31c5768f04363..17b7b70c301b9c0ab6a2a48c34c0a4fd3ad3db1a 100644 (file)
@@ -126,7 +126,7 @@ mod test {
 
     use thread::Thread;
     use super::{ONCE_INIT, Once};
-    use comm::channel;
+    use sync::mpsc::channel;
 
     #[test]
     fn smoke_once() {
@@ -155,7 +155,7 @@ fn stampede_once() {
                     });
                     assert!(run);
                 }
-                tx.send(());
+                tx.send(()).unwrap();
             }).detach();
         }
 
@@ -168,7 +168,7 @@ fn stampede_once() {
         }
 
         for _ in range(0u, 10) {
-            rx.recv();
+            rx.recv().unwrap();
         }
     }
 }
index b316cd908b6c625966daacc515dd9b490340e677..3c4283c72e2a08185ce4f87562662bd0aea70954 100644 (file)
@@ -363,7 +363,7 @@ mod tests {
     use prelude::v1::*;
 
     use rand::{mod, Rng};
-    use comm::channel;
+    use sync::mpsc::channel;
     use thread::Thread;
     use sync::{Arc, RWLock, StaticRWLock, RWLOCK_INIT};
 
@@ -408,7 +408,7 @@ fn frob() {
             }).detach();
         }
         drop(tx);
-        let _ = rx.recv_opt();
+        let _ = rx.recv();
         unsafe { R.destroy(); }
     }
 
@@ -475,7 +475,7 @@ fn test_rw_arc() {
                 Thread::yield_now();
                 *lock = tmp + 1;
             }
-            tx.send(());
+            tx.send(()).unwrap();
         }).detach();
 
         // Readers try to catch the writer in the act
@@ -494,7 +494,7 @@ fn test_rw_arc() {
         }
 
         // Wait for writer to finish
-        rx.recv();
+        rx.recv().unwrap();
         let lock = arc.read();
         assert_eq!(*lock, 10);
     }
index 382caa2cf4a9d9516f71adefe63587b9d3c8c79e..784b173b99eb879210d70606d1acce209e1513c6 100644 (file)
@@ -108,7 +108,7 @@ mod tests {
 
     use sync::Arc;
     use super::Semaphore;
-    use comm::channel;
+    use sync::mpsc::channel;
     use thread::Thread;
 
     #[test]
@@ -143,7 +143,7 @@ fn test_sem_as_cvar() {
         let s2 = s.clone();
         let _t = Thread::spawn(move|| {
             s2.acquire();
-            tx.send(());
+            tx.send(()).unwrap();
         });
         s.release();
         let _ = rx.recv();
@@ -157,7 +157,7 @@ fn test_sem_as_cvar() {
             let _ = rx.recv();
         });
         s.acquire();
-        tx.send(());
+        tx.send(()).unwrap();
     }
 
     #[test]
@@ -171,11 +171,11 @@ fn test_sem_multi_resource() {
         let _t = Thread::spawn(move|| {
             let _g = s2.access();
             let _ = rx2.recv();
-            tx1.send(());
+            tx1.send(()).unwrap();
         });
         let _g = s.access();
-        tx2.send(());
-        let _ = rx1.recv();
+        tx2.send(()).unwrap();
+        rx1.recv().unwrap();
     }
 
     #[test]
@@ -186,12 +186,12 @@ fn test_sem_runtime_friendly_blocking() {
         {
             let _g = s.access();
             Thread::spawn(move|| {
-                tx.send(());
+                tx.send(()).unwrap();
                 drop(s2.access());
-                tx.send(());
+                tx.send(()).unwrap();
             }).detach();
-            rx.recv(); // wait for child to come alive
+            rx.recv().unwrap(); // wait for child to come alive
         }
-        rx.recv(); // wait for child to be done
+        rx.recv().unwrap(); // wait for child to be done
     }
 }
index ce7e883e80357ea6436cb06e59d435beed5861ba..b03259983582a239dec1def3a84f118141cc1156 100644 (file)
@@ -12,9 +12,9 @@
 
 use core::prelude::*;
 
-use thread::Thread;
-use comm::{channel, Sender, Receiver};
 use sync::{Arc, Mutex};
+use sync::mpsc::{channel, Sender, Receiver};
+use thread::Thread;
 use thunk::Thunk;
 
 struct Sentinel<'a> {
@@ -55,7 +55,7 @@ fn drop(&mut self) {
 /// ```rust
 /// use std::sync::TaskPool;
 /// use std::iter::AdditiveIterator;
-/// use std::comm::channel;
+/// use std::sync::mpsc::channel;
 ///
 /// let pool = TaskPool::new(4u);
 ///
@@ -63,7 +63,7 @@ fn drop(&mut self) {
 /// for _ in range(0, 8u) {
 ///     let tx = tx.clone();
 ///     pool.execute(move|| {
-///         tx.send(1u);
+///         tx.send(1u).unwrap();
 ///     });
 /// }
 ///
@@ -101,7 +101,7 @@ pub fn new(tasks: uint) -> TaskPool {
     pub fn execute<F>(&self, job: F)
         where F : FnOnce(), F : Send
     {
-        self.jobs.send(Thunk::new(job));
+        self.jobs.send(Thunk::new(job)).unwrap();
     }
 }
 
@@ -115,7 +115,7 @@ fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk>>>) {
                 // Only lock jobs for the time it takes
                 // to get a job, not run it.
                 let lock = jobs.lock();
-                lock.recv_opt()
+                lock.recv()
             };
 
             match message {
@@ -134,7 +134,7 @@ fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk>>>) {
 mod test {
     use prelude::v1::*;
     use super::*;
-    use comm::channel;
+    use sync::mpsc::channel;
 
     const TEST_TASKS: uint = 4u;
 
@@ -148,7 +148,7 @@ fn test_works() {
         for _ in range(0, TEST_TASKS) {
             let tx = tx.clone();
             pool.execute(move|| {
-                tx.send(1u);
+                tx.send(1u).unwrap();
             });
         }
 
@@ -177,7 +177,7 @@ fn test_recovery_from_subtask_panic() {
         for _ in range(0, TEST_TASKS) {
             let tx = tx.clone();
             pool.execute(move|| {
-                tx.send(1u);
+                tx.send(1u).unwrap();
             });
         }
 
index 5d94e8efeb86c771c9b1c4fe037e5e71bbc92476..b9dc5f0e39845bd1a1f66c93b9de167b656aecf0 100644 (file)
 use prelude::v1::*;
 
 use cell::UnsafeCell;
-use comm::{channel, Sender, Receiver};
 use mem;
 use rt;
 use sync::{StaticMutex, StaticCondvar};
+use sync::mpsc::{channel, Sender, Receiver};
 use sys::helper_signal;
 
 use thread::Thread;
@@ -118,7 +118,7 @@ pub fn send(&'static self, msg: M) {
             // message. Otherwise it could wake up and go to sleep before we
             // send the message.
             assert!(!self.chan.get().is_null());
-            (**self.chan.get()).send(msg);
+            (**self.chan.get()).send(msg).unwrap();
             helper_signal::signal(*self.signal.get() as helper_signal::signal);
         }
     }
index 9824c9c7364f10188d9e6df48b2dd0645977653d..a11fe3487a8e422e3d741a3de58f1f7ae625ccdc 100644 (file)
@@ -13,7 +13,6 @@
 
 use c_str::{CString, ToCStr};
 use collections;
-use comm::{channel, Sender, Receiver};
 use hash::Hash;
 use io::process::{ProcessExit, ExitStatus, ExitSignal};
 use io::{mod, IoResult, IoError, EndOfFile};
@@ -22,6 +21,7 @@
 use os;
 use path::BytesContainer;
 use ptr;
+use sync::mpsc::{channel, Sender, Receiver};
 use sys::fs::FileDesc;
 use sys::{mod, retry, c, wouldblock, set_nonblocking, ms_to_timeval};
 use sys_common::helper_thread::Helper;
@@ -277,8 +277,8 @@ fn setgroups(ngroups: libc::c_int,
     }
 
     pub fn wait(&self, deadline: u64) -> IoResult<ProcessExit> {
-        use std::cmp;
-        use std::comm;
+        use cmp;
+        use sync::mpsc::TryRecvError;
 
         static mut WRITE_FD: libc::c_int = 0;
 
@@ -337,9 +337,9 @@ pub fn wait(&self, deadline: u64) -> IoResult<ProcessExit> {
 
         let (tx, rx) = channel();
         unsafe { HELPER.send(NewChild(self.pid, tx, deadline)); }
-        return match rx.recv_opt() {
+        return match rx.recv() {
             Ok(e) => Ok(e),
-            Err(()) => Err(timeout("wait timed out")),
+            Err(..) => Err(timeout("wait timed out")),
         };
 
         // Register a new SIGCHLD handler, returning the reading half of the
@@ -420,11 +420,11 @@ fn waitpid_helper(input: libc::c_int,
                             Ok(NewChild(pid, tx, deadline)) => {
                                 active.push((pid, tx, deadline));
                             }
-                            Err(comm::Disconnected) => {
+                            Err(TryRecvError::Disconnected) => {
                                 assert!(active.len() == 0);
                                 break 'outer;
                             }
-                            Err(comm::Empty) => break,
+                            Err(TryRecvError::Empty) => break,
                         }
                     }
                 }
@@ -460,7 +460,7 @@ fn waitpid_helper(input: libc::c_int,
                     active.retain(|&(pid, ref tx, _)| {
                         let pr = Process { pid: pid };
                         match pr.try_wait() {
-                            Some(msg) => { tx.send(msg); false }
+                            Some(msg) => { tx.send(msg).unwrap(); false }
                             None => true,
                         }
                     });
index 903c4954f6fa71fc6f23a91bedfcf68f2cf2443b..4afe13d87357d01676ee01110347511f8fc36d35 100644 (file)
 use prelude::v1::*;
 use self::Req::*;
 
-use comm::{mod, channel, Sender, Receiver};
 use io::IoResult;
 use libc;
 use mem;
 use os;
 use ptr;
 use sync::atomic;
+use sync::mpsc::{channel, Sender, Receiver, TryRecvError};
 use sys::c;
 use sys::fs::FileDesc;
 use sys_common::helper_thread::Helper;
@@ -168,7 +168,7 @@ fn signal(active: &mut Vec<Box<Inner>>,
             1 => {
                 loop {
                     match messages.try_recv() {
-                        Err(comm::Disconnected) => {
+                        Err(TryRecvError::Disconnected) => {
                             assert!(active.len() == 0);
                             break 'outer;
                         }
@@ -179,7 +179,7 @@ fn signal(active: &mut Vec<Box<Inner>>,
                             match dead.iter().position(|&(i, _)| id == i) {
                                 Some(i) => {
                                     let (_, i) = dead.remove(i).unwrap();
-                                    ack.send(i);
+                                    ack.send(i).unwrap();
                                     continue
                                 }
                                 None => {}
@@ -187,7 +187,7 @@ fn signal(active: &mut Vec<Box<Inner>>,
                             let i = active.iter().position(|i| i.id == id);
                             let i = i.expect("no timer found");
                             let t = active.remove(i).unwrap();
-                            ack.send(t);
+                            ack.send(t).unwrap();
                         }
                         Err(..) => break
                     }
@@ -271,7 +271,7 @@ fn inner(&mut self) -> Box<Inner> {
             None => {
                 let (tx, rx) = channel();
                 HELPER.send(RemoveTimer(self.id, tx));
-                rx.recv()
+                rx.recv().unwrap()
             }
         }
     }
index fdf2648faa1c8ae45bb915417eb73e0bafb24547..5c9e6153afb41d777e2ea699f9800556ca55c4f1 100644 (file)
@@ -443,7 +443,7 @@ mod test {
 
     use any::{Any, AnyRefExt};
     use boxed::BoxAny;
-    use comm::{channel, Sender};
+    use sync::mpsc::{channel, Sender};
     use result;
     use std::io::{ChanReader, ChanWriter};
     use super::{Thread, Builder};
@@ -470,9 +470,9 @@ fn test_named_thread() {
     fn test_run_basic() {
         let (tx, rx) = channel();
         Thread::spawn(move|| {
-            tx.send(());
+            tx.send(()).unwrap();
         }).detach();
-        rx.recv();
+        rx.recv().unwrap();
     }
 
     #[test]
@@ -505,7 +505,7 @@ fn f(i: int, tx: Sender<()>) {
             let tx = tx.clone();
             Thread::spawn(move|| {
                 if i == 0 {
-                    tx.send(());
+                    tx.send(()).unwrap();
                 } else {
                     f(i - 1, tx);
                 }
@@ -513,7 +513,7 @@ fn f(i: int, tx: Sender<()>) {
 
         }
         f(10, tx);
-        rx.recv();
+        rx.recv().unwrap();
     }
 
     #[test]
@@ -522,11 +522,11 @@ fn test_spawn_sched_childs_on_default_sched() {
 
         Thread::spawn(move|| {
             Thread::spawn(move|| {
-                tx.send(());
+                tx.send(()).unwrap();
             }).detach();
         }).detach();
 
-        rx.recv();
+        rx.recv().unwrap();
     }
 
     fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Thunk) {
@@ -537,10 +537,10 @@ fn avoid_copying_the_body<F>(spawnfn: F) where F: FnOnce(Thunk) {
 
         spawnfn(Thunk::new(move|| {
             let x_in_child = (&*x) as *const int as uint;
-            tx.send(x_in_child);
+            tx.send(x_in_child).unwrap();
         }));
 
-        let x_in_child = rx.recv();
+        let x_in_child = rx.recv().unwrap();
         assert_eq!(x_in_parent, x_in_child);
     }
 
index 674cb5a98057caa1733b31bd3caaed8df2224e58..6cd26a366aef91ac1a5366df51afb60d1071be8a 100644 (file)
@@ -471,7 +471,7 @@ unsafe fn ptr(&'static self) -> Option<*mut T> {
 mod tests {
     use prelude::v1::*;
 
-    use comm::{channel, Sender};
+    use sync::mpsc::{channel, Sender};
     use cell::UnsafeCell;
     use thread::Thread;
 
@@ -480,7 +480,7 @@ mod tests {
     impl Drop for Foo {
         fn drop(&mut self) {
             let Foo(ref s) = *self;
-            s.send(());
+            s.send(()).unwrap();
         }
     }
 
@@ -497,9 +497,9 @@ fn smoke_no_dtor() {
             FOO.with(|f| unsafe {
                 assert_eq!(*f.get(), 1);
             });
-            tx.send(());
+            tx.send(()).unwrap();
         });
-        rx.recv();
+        rx.recv().unwrap();
 
         FOO.with(|f| unsafe {
             assert_eq!(*f.get(), 2);
@@ -519,7 +519,7 @@ fn smoke_dtor() {
                 *f.get() = Some(Foo(tx.take().unwrap()));
             });
         });
-        rx.recv();
+        rx.recv().unwrap();
     }
 
     #[test]
@@ -610,7 +610,7 @@ fn drop(&mut self) {
             let mut tx = Some(tx);
             K1.with(|s| *s.get() = Some(S1(tx.take().unwrap())));
         });
-        rx.recv();
+        rx.recv().unwrap();
     }
 }
 
index fc9826a913cd85f446c89fce0e5df351c73495a3..c70aa41c569cd0c8253c50659bd0ee27bdc5035b 100644 (file)
@@ -59,7 +59,6 @@
 use std::any::{Any, AnyRefExt};
 use std::cmp;
 use std::collections::BTreeMap;
-use std::comm::{channel, Sender};
 use std::f64;
 use std::fmt::Show;
 use std::fmt;
@@ -71,6 +70,7 @@
 use std::num::{Float, FloatMath, Int};
 use std::os;
 use std::str::{FromStr, from_str};
+use std::sync::mpsc::{channel, Sender};
 use std::thread::{mod, Thread};
 use std::thunk::{Thunk, Invoke};
 use std::time::Duration;
@@ -1021,7 +1021,7 @@ fn run_tests<F>(opts: &TestOpts,
             pending += 1;
         }
 
-        let (desc, result, stdout) = rx.recv();
+        let (desc, result, stdout) = rx.recv().unwrap();
         if concurrency != 1 {
             try!(callback(TeWait(desc.clone(), PadNone)));
         }
@@ -1034,7 +1034,7 @@ fn run_tests<F>(opts: &TestOpts,
     for b in filtered_benchs_and_metrics.into_iter() {
         try!(callback(TeWait(b.desc.clone(), b.testfn.padding())));
         run_test(opts, !opts.run_benchmarks, b, tx.clone());
-        let (test, result, stdout) = rx.recv();
+        let (test, result, stdout) = rx.recv().unwrap();
         try!(callback(TeResult(test, result, stdout)));
     }
     Ok(())
@@ -1111,7 +1111,7 @@ pub fn run_test(opts: &TestOpts,
     let TestDescAndFn {desc, testfn} = test;
 
     if force_ignore || desc.ignore {
-        monitor_ch.send((desc, TrIgnored, Vec::new()));
+        monitor_ch.send((desc, TrIgnored, Vec::new())).unwrap();
         return;
     }
 
@@ -1138,31 +1138,31 @@ fn run_test_inner(desc: TestDesc,
             let result_guard = cfg.spawn(move || { testfn.invoke(()) });
             let stdout = reader.read_to_end().unwrap().into_iter().collect();
             let test_result = calc_result(&desc, result_guard.join());
-            monitor_ch.send((desc.clone(), test_result, stdout));
+            monitor_ch.send((desc.clone(), test_result, stdout)).unwrap();
         }).detach();
     }
 
     match testfn {
         DynBenchFn(bencher) => {
             let bs = ::bench::benchmark(|harness| bencher.run(harness));
-            monitor_ch.send((desc, TrBench(bs), Vec::new()));
+            monitor_ch.send((desc, TrBench(bs), Vec::new())).unwrap();
             return;
         }
         StaticBenchFn(benchfn) => {
             let bs = ::bench::benchmark(|harness| (benchfn.clone())(harness));
-            monitor_ch.send((desc, TrBench(bs), Vec::new()));
+            monitor_ch.send((desc, TrBench(bs), Vec::new())).unwrap();
             return;
         }
         DynMetricFn(f) => {
             let mut mm = MetricMap::new();
             f.invoke(&mut mm);
-            monitor_ch.send((desc, TrMetrics(mm), Vec::new()));
+            monitor_ch.send((desc, TrMetrics(mm), Vec::new())).unwrap();
             return;
         }
         StaticMetricFn(f) => {
             let mut mm = MetricMap::new();
             f(&mut mm);
-            monitor_ch.send((desc, TrMetrics(mm), Vec::new()));
+            monitor_ch.send((desc, TrMetrics(mm), Vec::new())).unwrap();
             return;
         }
         DynTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, f),
@@ -1466,7 +1466,7 @@ mod tests {
                StaticTestName, DynTestName, DynTestFn, ShouldFail};
     use std::io::TempDir;
     use std::thunk::Thunk;
-    use std::comm::channel;
+    use std::sync::mpsc::channel;
 
     #[test]
     pub fn do_not_run_ignored_tests() {
@@ -1481,7 +1481,7 @@ pub fn do_not_run_ignored_tests() {
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
-        let (_, res, _) = rx.recv();
+        let (_, res, _) = rx.recv().unwrap();
         assert!(res != TrOk);
     }
 
@@ -1498,7 +1498,7 @@ fn f() { }
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
-        let (_, res, _) = rx.recv();
+        let (_, res, _) = rx.recv().unwrap();
         assert!(res == TrIgnored);
     }
 
@@ -1515,7 +1515,7 @@ fn test_should_fail() {
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
-        let (_, res, _) = rx.recv();
+        let (_, res, _) = rx.recv().unwrap();
         assert!(res == TrOk);
     }
 
@@ -1532,7 +1532,7 @@ fn test_should_fail_good_message() {
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
-        let (_, res, _) = rx.recv();
+        let (_, res, _) = rx.recv().unwrap();
         assert!(res == TrOk);
     }
 
@@ -1549,7 +1549,7 @@ fn test_should_fail_bad_message() {
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
-        let (_, res, _) = rx.recv();
+        let (_, res, _) = rx.recv().unwrap();
         assert!(res == TrFailed);
     }
 
@@ -1566,7 +1566,7 @@ fn f() { }
         };
         let (tx, rx) = channel();
         run_test(&TestOpts::new(), false, desc, tx);
-        let (_, res, _) = rx.recv();
+        let (_, res, _) = rx.recv().unwrap();
         assert!(res == TrFailed);
     }
 
index e3dbe3c7e225abd829a7b6e8d3efa70d4f8e2892..ec470ddc21343fdd684691d95856e502c31a5089 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::task;
-use std::comm::{Receiver, channel};
+use std::sync::mpsc::{Receiver, channel};
 
 pub fn foo<T:Send + Clone>(x: T) -> Receiver<T> {
     let (tx, rx) = channel();
index 90d5072f412e7827fe6fa4c7cbbd03882f64b8df..bb6060f2543e2a846cead159de024b47647bc76e 100644 (file)
@@ -8,15 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::channel;
+use std::sync::mpsc::channel;
 
 fn main() {
     let (tx, rx) = channel();
     let x = Some(rx);
     tx.send(false);
     match x {
-        Some(z) if z.recv() => { panic!() }, //~ ERROR cannot bind by-move into a pattern guard
-        Some(z) => { assert!(!z.recv()); },
+        Some(z) if z.recv().unwrap() => { panic!() },
+            //~^ ERROR cannot bind by-move into a pattern guard
+        Some(z) => { assert!(!z.recv().unwrap()); },
         None => panic!()
     }
 }
index 6228b92472924fa582c24d1983ee7a2151d146b3..9826a5a0126f41351b7e73bc31a0f37b0776703e 100644 (file)
@@ -11,7 +11,7 @@
 // Tests (negatively) the ability for the Self type in default methods
 // to use capabilities granted by builtin kinds as supertraits.
 
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 
 trait Foo : Sync+'static {
     fn foo(self, mut chan: Sender<Self>) { }
index 83e329db0da2e48d61a2764d8bca9befea167343..2e535b3950938cbb2bdbf7e51ed303075d2d651b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::Receiver;
+use std::sync::mpsc::Receiver;
 
 fn test<T: Sync>() {}
 
index 296b4187a1f532ed2ce989dc15196794bd16379a..1b1c43e4793e339c42a7a623c3a93d201a398e3b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::Sender;
+use std::sync::mpsc::Sender;
 
 fn test<T: Sync>() {}
 
index f42e1a1bc15edf22f5431c68dd704298453f20f4..094f6d64edc2ea10b2b71bff791cdcb81906d3dc 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::channel;
+use std::sync::mpsc::channel;
 use std::thread::Thread;
 
 fn main() {
index 312f26394b24d341abca24d7aaa96af11882c34e..993df8e59f3e041e1b6de10f1381e657ea7f81a7 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::channel;
+use std::sync::mpsc::channel;
 
 // Test that a class with an unsendable field can't be
 // sent
index 45710408172d092a8a1c72e796de4500707f06ca..b3c4802530ed3c9f7aa38a0ea43af498648f91d1 100644 (file)
@@ -10,7 +10,7 @@
 
 // Basic boolean tests
 
-use std::cmp::{Equal, Greater, Less};
+use std::cmp::Ordering::{Equal, Greater, Less};
 use std::ops::{BitAnd, BitOr, BitXor};
 
 fn main() {
index 83c1696f7b2ab3fb367dff531b30c3075ce17c15..365670db6f928bf60b89c1d4df8e08a5396ff95c 100644 (file)
@@ -14,7 +14,7 @@
 // a Send. Basically this just makes sure rustc is using
 // each_bound_trait_and_supertraits in type_contents correctly.
 
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 
 trait Bar : Send { }
 trait Foo : Bar { }
@@ -23,11 +23,11 @@ impl <T: Send> Foo for T { }
 impl <T: Send> Bar for T { }
 
 fn foo<T: Foo>(val: T, chan: Sender<T>) {
-    chan.send(val);
+    chan.send(val).unwrap();
 }
 
 pub fn main() {
     let (tx, rx) = channel();
     foo(31337i, tx);
-    assert!(rx.recv() == 31337i);
+    assert!(rx.recv().unwrap() == 31337i);
 }
index 1f002ec79c61eb975ad5f4934ed68dbf6048fcf2..1f42076f6d6e1822c367428110f6d3f3153f387d 100644 (file)
@@ -16,7 +16,7 @@
 
 extern crate trait_superkinds_in_metadata;
 
-use std::comm::{channel, Sender, Receiver};
+use std::sync::mpsc::{channel, Sender, Receiver};
 use trait_superkinds_in_metadata::{RequiresRequiresShareAndSend, RequiresShare};
 
 #[deriving(PartialEq)]
@@ -26,11 +26,11 @@ impl <T: Sync> RequiresShare for X<T> { }
 impl <T: Sync+Send> RequiresRequiresShareAndSend for X<T> { }
 
 fn foo<T: RequiresRequiresShareAndSend>(val: T, chan: Sender<T>) {
-    chan.send(val);
+    chan.send(val).unwrap();
 }
 
 pub fn main() {
     let (tx, rx): (Sender<X<int>>, Receiver<X<int>>) = channel();
     foo(X(31337i), tx);
-    assert!(rx.recv() == X(31337i));
+    assert!(rx.recv().unwrap() == X(31337i));
 }
index 46ad3f93b0bb79413ce84fdf424b663d4cecd0a0..7f4a2398f54ba06fc702575d07bd30c9ed0d7586 100644 (file)
 // builtin-kinds, e.g., if a trait requires Send to implement, then
 // at usage site of that trait, we know we have the Send capability.
 
-use std::comm::{channel, Sender, Receiver};
+use std::sync::mpsc::{channel, Sender, Receiver};
 
 trait Foo : Send { }
 
 impl <T: Send> Foo for T { }
 
 fn foo<T: Foo>(val: T, chan: Sender<T>) {
-    chan.send(val);
+    chan.send(val).unwrap();
 }
 
 pub fn main() {
     let (tx, rx): (Sender<int>, Receiver<int>) = channel();
     foo(31337i, tx);
-    assert!(rx.recv() == 31337i);
+    assert!(rx.recv().unwrap() == 31337i);
 }
index 27a7cd909fefec1a7678878518317e339405b671..bf06bf8b8c65ae7f39b99322c795860066506e97 100644 (file)
 // Tests the ability for the Self type in default methods to use
 // capabilities granted by builtin kinds as supertraits.
 
-use std::comm::{Sender, channel};
+use std::sync::mpsc::{Sender, channel};
 
 trait Foo : Send {
     fn foo(self, tx: Sender<Self>) {
-        tx.send(self);
+        tx.send(self).unwrap();
     }
 }
 
@@ -24,5 +24,5 @@ impl <T: Send> Foo for T { }
 pub fn main() {
     let (tx, rx) = channel();
     1193182i.foo(tx);
-    assert!(rx.recv() == 1193182i);
+    assert!(rx.recv().unwrap() == 1193182i);
 }
index 4ed444f92ac92b34da999d80b34f29f91b1da658..3f6d6a02c79264d3d751a8fcf62d5ab1d1d06f61 100644 (file)
@@ -17,7 +17,7 @@
 extern crate log;
 
 use log::{set_logger, Logger, LogRecord};
-use std::comm::channel;
+use std::sync::mpsc::channel;
 use std::fmt;
 use std::io::{ChanReader, ChanWriter};
 use std::thread::Thread;
index c4bf8131506228ff9c4e2b8b46a598ae23fc9cfe..8b2947ba3eef03f4f94623648bc1b70d5db58747 100644 (file)
@@ -16,5 +16,5 @@
 extern crate cci_capture_clause;
 
 pub fn main() {
-    cci_capture_clause::foo(()).recv()
+    cci_capture_clause::foo(()).recv().unwrap();
 }
index e1dc5802162eb8cd41d14f4bd3f08d20ee4978e0..816b28c3a9ae1e3b8e074a9a9e5c491c6ca743f1 100644 (file)
@@ -10,7 +10,7 @@
 
 #![feature(unboxed_closures)]
 
-use std::comm::channel;
+use std::sync::mpsc::channel;
 
 fn foo<F:FnOnce()+Send>(blk: F) {
     blk();
@@ -19,7 +19,7 @@ fn foo<F:FnOnce()+Send>(blk: F) {
 pub fn main() {
     let (tx, rx) = channel();
     foo(move || {
-        tx.send(());
+        tx.send(()).unwrap();
     });
-    rx.recv();
+    rx.recv().unwrap();
 }
index 119bdaff98ee812f13ce0b6325d4630625470cba..5cfc692aae43dda50e4431a126b25efd78bbd495 100644 (file)
@@ -9,12 +9,12 @@
 // except according to those terms.
 
 use std::task;
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 
 pub fn main() {
     let (tx, rx) = channel();
     let _t = task::spawn(move|| { child(&tx) });
-    let y = rx.recv();
+    let y = rx.recv().unwrap();
     println!("received");
     println!("{}", y);
     assert_eq!(y, 10);
@@ -22,6 +22,6 @@ pub fn main() {
 
 fn child(c: &Sender<int>) {
     println!("sending");
-    c.send(10);
+    c.send(10).unwrap();
     println!("value sent");
 }
index 198915fe02ed89e6ebc09e0e9618e9e3b5cfab89..c1db8a6eb13f4f27a39e0504b69f89cb2b893608 100644 (file)
@@ -23,7 +23,7 @@
 use std::io::{Process, Command, timer};
 use std::time::Duration;
 use std::str;
-use std::comm::channel;
+use std::sync::mpsc::channel;
 use std::thread::Thread;
 
 macro_rules! succeed( ($e:expr) => (
@@ -88,13 +88,13 @@ pub fn test_destroy_actually_kills(force: bool) {
     let rx2 = t.oneshot(Duration::milliseconds(1000));
     Thread::spawn(move|| {
         select! {
-            () = rx2.recv() => unsafe { libc::exit(1) },
-            () = rx1.recv() => {}
+            _ = rx2.recv() => unsafe { libc::exit(1) },
+            _ = rx1.recv() => {}
         }
     }).detach();
     match p.wait().unwrap() {
         ExitStatus(..) => panic!("expected a signal"),
-        ExitSignal(..) => tx.send(()),
+        ExitSignal(..) => tx.send(()).unwrap(),
     }
 }
 
index bca61ab1bd38718e2e2a1016565cf4fae3efe74d..1ad0e87b6453e792786a28c964cf5c6ee2e95bcd 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::task;
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 
 #[deriving(PartialEq, Show)]
 enum Message {
@@ -23,7 +23,7 @@ struct SendOnDrop {
 
 impl Drop for SendOnDrop {
     fn drop(&mut self) {
-        self.sender.send(Message::Dropped);
+        self.sender.send(Message::Dropped).unwrap();
     }
 }
 
@@ -37,10 +37,10 @@ impl Drop for Foo {
     fn drop(&mut self) {
         match self {
             &Foo::SimpleVariant(ref mut sender) => {
-                sender.send(Message::DestructorRan);
+                sender.send(Message::DestructorRan).unwrap();
             }
             &Foo::NestedVariant(_, _, ref mut sender) => {
-                sender.send(Message::DestructorRan);
+                sender.send(Message::DestructorRan).unwrap();
             }
             &Foo::FailingVariant { .. } => {
                 panic!("Failed");
@@ -54,23 +54,23 @@ pub fn main() {
     {
         let v = Foo::SimpleVariant(sender);
     }
-    assert_eq!(receiver.recv(), Message::DestructorRan);
-    assert_eq!(receiver.recv_opt().ok(), None);
+    assert_eq!(receiver.recv().unwrap(), Message::DestructorRan);
+    assert_eq!(receiver.recv().ok(), None);
 
     let (sender, receiver) = channel();
     {
         let v = Foo::NestedVariant(box 42u, SendOnDrop { sender: sender.clone() }, sender);
     }
-    assert_eq!(receiver.recv(), Message::DestructorRan);
-    assert_eq!(receiver.recv(), Message::Dropped);
-    assert_eq!(receiver.recv_opt().ok(), None);
+    assert_eq!(receiver.recv().unwrap(), Message::DestructorRan);
+    assert_eq!(receiver.recv().unwrap(), Message::Dropped);
+    assert_eq!(receiver.recv().ok(), None);
 
     let (sender, receiver) = channel();
     task::spawn(move|| {
         let v = Foo::FailingVariant { on_drop: SendOnDrop { sender: sender } };
     });
-    assert_eq!(receiver.recv(), Message::Dropped);
-    assert_eq!(receiver.recv_opt().ok(), None);
+    assert_eq!(receiver.recv().unwrap(), Message::Dropped);
+    assert_eq!(receiver.recv().ok(), None);
 
     let (sender, receiver) = channel();
     {
@@ -83,11 +83,11 @@ pub fn main() {
             v = Foo::FailingVariant { on_drop: SendOnDrop { sender: sender } };
         });
     }
-    assert_eq!(receiver.recv(), Message::DestructorRan);
-    assert_eq!(receiver.recv(), Message::Dropped);
-    assert_eq!(receiver.recv(), Message::DestructorRan);
-    assert_eq!(receiver.recv(), Message::Dropped);
-    assert_eq!(receiver.recv(), Message::DestructorRan);
-    assert_eq!(receiver.recv(), Message::Dropped);
-    assert_eq!(receiver.recv_opt().ok(), None);
+    assert_eq!(receiver.recv().unwrap(), Message::DestructorRan);
+    assert_eq!(receiver.recv().unwrap(), Message::Dropped);
+    assert_eq!(receiver.recv().unwrap(), Message::DestructorRan);
+    assert_eq!(receiver.recv().unwrap(), Message::Dropped);
+    assert_eq!(receiver.recv().unwrap(), Message::DestructorRan);
+    assert_eq!(receiver.recv().unwrap(), Message::Dropped);
+    assert_eq!(receiver.recv().ok(), None);
 }
index 6155ca6357237f00863164280d6fb25cfe073d94..162d7f1025589f0d1a753a4393503d76800077ba 100644 (file)
@@ -21,7 +21,7 @@ pub fn map(filename: String, emit: map_reduce::putter) {
 
 mod map_reduce {
     use std::collections::HashMap;
-    use std::comm::{channel, Sender};
+    use std::sync::mpsc::{channel, Sender};
     use std::str;
     use std::task;
 
@@ -50,16 +50,16 @@ fn emit(im: &mut HashMap<String, int>,
             }
             let (tx, rx) = channel();
             println!("sending find_reducer");
-            ctrl.send(ctrl_proto::find_reducer(key.as_bytes().to_vec(), tx));
+            ctrl.send(ctrl_proto::find_reducer(key.as_bytes().to_vec(), tx)).unwrap();
             println!("receiving");
-            let c = rx.recv();
+            let c = rx.recv().unwrap();
             println!("{}", c);
             im.insert(key, c);
         }
 
         let ctrl_clone = ctrl.clone();
         ::map(input, |a,b| emit(&mut intermediates, ctrl.clone(), a, b) );
-        ctrl_clone.send(ctrl_proto::mapper_done);
+        ctrl_clone.send(ctrl_proto::mapper_done).unwrap();
     }
 
     pub fn map_reduce(inputs: Vec<String>) {
@@ -77,7 +77,7 @@ pub fn map_reduce(inputs: Vec<String>) {
         let mut num_mappers = inputs.len() as int;
 
         while num_mappers > 0 {
-            match rx.recv() {
+            match rx.recv().unwrap() {
               ctrl_proto::mapper_done => { num_mappers -= 1; }
               ctrl_proto::find_reducer(k, cc) => {
                 let mut c;
@@ -86,7 +86,7 @@ pub fn map_reduce(inputs: Vec<String>) {
                   Some(&_c) => { c = _c; }
                   None => { c = 0; }
                 }
-                cc.send(c);
+                cc.send(c).unwrap();
               }
             }
         }
index e6da859c110e734cbeedb53735eb775e933bfd4e..b9339c1cc0d03ad030a746487036669e53b173bb 100644 (file)
 // This test may not always fail, but it can be flaky if the race it used to
 // expose is still present.
 
-use std::comm::{channel, Sender, Receiver};
+use std::sync::mpsc::{channel, Sender, Receiver};
 use std::thread::Thread;
 
 fn helper(rx: Receiver<Sender<()>>) {
     for tx in rx.iter() {
-        let _ = tx.send_opt(());
+        let _ = tx.send(());
     }
 }
 
@@ -25,11 +25,11 @@ fn main() {
     let _t = Thread::spawn(move|| { helper(rx) }).detach();
     let (snd, rcv) = channel::<int>();
     for _ in range(1i, 100000i) {
-        snd.send(1i);
+        snd.send(1i).unwrap();
         let (tx2, rx2) = channel();
-        tx.send(tx2);
+        tx.send(tx2).unwrap();
         select! {
-            () = rx2.recv() => (),
+            _ = rx2.recv() => (),
             _ = rcv.recv() => ()
         }
     }
index df2a9e6bfa9094ab24da3f0cd54dcc8813329920..a02dbb6035bfadff43dd21901ed6c602f96c8954 100644 (file)
@@ -11,7 +11,7 @@
 #![feature(default_type_params)]
 
 use std::task;
-use std::comm::Sender;
+use std::sync::mpsc::Sender;
 use std::thunk::Invoke;
 
 type RingBuffer = Vec<f64> ;
index 871e52e3639541e263973e54216fa427a886098a..30e1a14ecff8fc776f44862abb78e940be73911c 100644 (file)
@@ -9,15 +9,15 @@
 // except according to those terms.
 
 use std::io::println;
-use std::comm::channel;
+use std::sync::mpsc::channel;
 use std::thread::Thread;
 
 pub fn main() {
     let (tx, rx) = channel();
 
-    tx.send("hello, world");
+    tx.send("hello, world").unwrap();
 
     Thread::spawn(move|| {
-        println(rx.recv());
+        println(rx.recv().unwrap());
     }).join().ok().unwrap();
 }
index 6692988f6da29f5824f348dd58c7714845200f6b..7e53722726f2cef8d53b748ccd69ee0fb0085c60 100644 (file)
@@ -8,15 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::task;
-use std::comm::channel;
+use std::sync::mpsc::channel;
+use std::thread::Thread;
 
 pub fn main() {
     let (tx, rx) = channel::<&'static str>();
 
-    task::spawn(move|| {
-        assert_eq!(rx.recv(), "hello, world");
+    let t = Thread::spawn(move|| {
+        assert_eq!(rx.recv().unwrap(), "hello, world");
     });
 
-    tx.send("hello, world");
+    tx.send("hello, world").unwrap();
+    t.join().ok().unwrap();
 }
index 4163ebf4573fcdb79b27db98ba448e2b59e75488..39695a8339f08aa0017ff4baa150b8df4380b68d 100644 (file)
@@ -9,19 +9,19 @@
 // except according to those terms.
 
 use std::thread::Thread;
-use std::comm::{channel, Receiver};
+use std::sync::mpsc::{channel, Receiver};
 
 fn periodical(n: int) -> Receiver<bool> {
     let (chan, port) = channel();
     Thread::spawn(move|| {
         loop {
             for _ in range(1, n) {
-                match chan.send_opt(false) {
+                match chan.send(false) {
                     Ok(()) => {}
                     Err(..) => break,
                 }
             }
-            match chan.send_opt(true) {
+            match chan.send(true) {
                 Ok(()) => {}
                 Err(..) => break
             }
@@ -35,7 +35,7 @@ fn integers() -> Receiver<int> {
     Thread::spawn(move|| {
         let mut i = 1;
         loop {
-            match chan.send_opt(i) {
+            match chan.send(i) {
                 Ok(()) => {}
                 Err(..) => break,
             }
@@ -50,7 +50,7 @@ fn main() {
     let threes = periodical(3);
     let fives = periodical(5);
     for _ in range(1i, 100i) {
-        match (ints.recv(), threes.recv(), fives.recv()) {
+        match (ints.recv().unwrap(), threes.recv().unwrap(), fives.recv().unwrap()) {
             (_, true, true) => println!("FizzBuzz"),
             (_, true, false) => println!("Fizz"),
             (_, false, true) => println!("Buzz"),
index d3cbd556776401f93bef72cd1b7a155f6da7336a..34bb50c5cf669844524b7c84a4899b74573be6db 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::{mod, channel};
+use std::sync::mpsc::{TryRecvError, channel};
 use std::io::timer::Timer;
 use std::thread::Thread;
 use std::time::Duration;
@@ -18,13 +18,13 @@ pub fn main() {
     let _t = Thread::spawn(move||{
         let mut timer = Timer::new().unwrap();
         timer.sleep(Duration::milliseconds(10));
-        tx.send(());
+        tx.send(()).unwrap();
     });
     loop {
         match rx.try_recv() {
             Ok(()) => break,
-            Err(comm::Empty) => {}
-            Err(comm::Disconnected) => unreachable!()
+            Err(TryRecvError::Empty) => {}
+            Err(TryRecvError::Disconnected) => unreachable!()
         }
     }
 }
index 2e6127541a1a1bf02aaa2096f2aa3157cbc7c982..a9a50b9ef25af6c44b729dac8fdebaad2690130d 100644 (file)
@@ -9,12 +9,12 @@
 // except according to those terms.
 
 use std::task;
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 
 fn producer(tx: &Sender<Vec<u8>>) {
     tx.send(
          vec!(1u8, 2u8, 3u8, 4u8, 5u8, 6u8, 7u8, 8u8, 9u8, 10u8, 11u8, 12u8,
-          13u8));
+          13u8)).unwrap();
 }
 
 pub fn main() {
@@ -23,5 +23,5 @@ pub fn main() {
         producer(&tx)
     });
 
-    let _data: Vec<u8> = rx.recv();
+    let _data: Vec<u8> = rx.recv().unwrap();
 }
index 8e547527f7297700879b2fe4d58ca97fe1583ba6..2612483ded486e8713b7cc4c95a3199f0f9ad18e 100644 (file)
@@ -14,7 +14,7 @@
 #[phase(plugin,link)]
 extern crate log;
 
-use std::comm::{channel, Sender, Receiver};
+use std::sync::mpsc::{channel, Sender, Receiver};
 use std::thread::Thread;
 
 pub struct ChannelLogger {
@@ -30,7 +30,7 @@ pub fn new() -> (Box<ChannelLogger>, Receiver<String>) {
 
 impl log::Logger for ChannelLogger {
     fn log(&mut self, record: &log::LogRecord) {
-        self.tx.send(format!("{}", record.args));
+        self.tx.send(format!("{}", record.args)).unwrap();
     }
 }
 
@@ -49,9 +49,9 @@ pub fn main() {
         info!("f1o");
     });
 
-    assert_eq!(rx.recv().as_slice(), "foo");
-    assert_eq!(rx.recv().as_slice(), "foo bar");
-    assert_eq!(rx.recv().as_slice(), "bar foo");
-    assert_eq!(rx.recv().as_slice(), "f1o");
-    assert!(rx.recv_opt().is_err());
+    assert_eq!(rx.recv().unwrap().as_slice(), "foo");
+    assert_eq!(rx.recv().unwrap().as_slice(), "foo bar");
+    assert_eq!(rx.recv().unwrap().as_slice(), "bar foo");
+    assert_eq!(rx.recv().unwrap().as_slice(), "f1o");
+    assert!(rx.recv().is_err());
 }
index 71620d05e014bb752e7c8b37731031b94eb99a14..7fd9706bd0fea88e056862837070494c0cf74832 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::task;
-use std::comm::channel;
+use std::sync::mpsc::channel;
 
 struct test {
   f: int,
@@ -30,10 +30,10 @@ pub fn main() {
 
     task::spawn(move|| {
         let (tx2, rx2) = channel();
-        tx.send(tx2);
+        tx.send(tx2).unwrap();
 
-        let _r = rx2.recv();
+        let _r = rx2.recv().unwrap();
     });
 
-    rx.recv().send(test(42));
+    rx.recv().unwrap().send(test(42)).unwrap();
 }
index 181874705da67770e867fc9d5a1bb03a732941d3..ae992a0a358d11b51239398916e2f9b863743625 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 
 // tests that ctrl's type gets inferred properly
 struct Command<K, V> {
index 3d5f0af0e3f40001e82124d7f25f647660aba635..8691d5e875bfc401fa3c0878b05a7d159b20a0b0 100644 (file)
@@ -10,7 +10,7 @@
 
 // Test that a class with only sendable fields can be sent
 
-use std::comm::channel;
+use std::sync::mpsc::channel;
 
 struct foo {
   i: int,
index e3b2a2903bcbafa81b1f9c93031cc120ecc26fc5..1c86e3e6ea23678a607db4d4efdca67c7ab247dc 100644 (file)
@@ -15,7 +15,7 @@
  */
 
 use std::task;
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 
 type ctx = Sender<int>;
 
index 7c664b21fade574a201b8050c9d72485aa2729af..de077ffd19020da5b2ef451ce8dfc96bbc838cab 100644 (file)
@@ -9,27 +9,27 @@
 // except according to those terms.
 
 use std::task;
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 
 pub fn main() { test05(); }
 
 fn test05_start(tx : &Sender<int>) {
-    tx.send(10);
+    tx.send(10).unwrap();
     println!("sent 10");
-    tx.send(20);
+    tx.send(20).unwrap();
     println!("sent 20");
-    tx.send(30);
+    tx.send(30).unwrap();
     println!("sent 30");
 }
 
 fn test05() {
     let (tx, rx) = channel();
     task::spawn(move|| { test05_start(&tx) });
-    let mut value: int = rx.recv();
+    let mut value: int = rx.recv().unwrap();
     println!("{}", value);
-    value = rx.recv();
+    value = rx.recv().unwrap();
     println!("{}", value);
-    value = rx.recv();
+    value = rx.recv().unwrap();
     println!("{}", value);
     assert_eq!(value, 30);
 }
index c35e2f2f37a40dd8739462f9897db9f5558a03a6..93dca923b6b98d287a0cda5562cb26353cd9d62f 100644 (file)
@@ -9,18 +9,18 @@
 // except according to those terms.
 
 use std::task;
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 
 fn start(tx: &Sender<Sender<String>>) {
     let (tx2, rx) = channel();
-    tx.send(tx2);
+    tx.send(tx2).unwrap();
 
     let mut a;
     let mut b;
-    a = rx.recv();
+    a = rx.recv().unwrap();
     assert!(a == "A".to_string());
     println!("{}", a);
-    b = rx.recv();
+    b = rx.recv().unwrap();
     assert!(b == "B".to_string());
     println!("{}", b);
 }
@@ -29,8 +29,8 @@ pub fn main() {
     let (tx, rx) = channel();
     let _child = task::spawn(move|| { start(&tx) });
 
-    let mut c = rx.recv();
-    c.send("A".to_string());
-    c.send("B".to_string());
+    let mut c = rx.recv().unwrap();
+    c.send("A".to_string()).unwrap();
+    c.send("B".to_string()).unwrap();
     task::deschedule();
 }
index 10b4e51631176d1fc2fdb4014c3fb81477793345..8168e84e42674a82faede730b9eb543da095967e 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 use std::task;
 
 fn start(tx: &Sender<Sender<int>>) {
index 31da1168bf7eb75cb50081c23ef0caa468f58c7b..bb92ef38728fa8509017574cf087b89d02707ce9 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 use std::task;
 
 fn start(tx: &Sender<int>, start: int, number_of_messages: int) {
index 8ec589d5db5fce8780012fceae016d405c50a1a2..d63cbd5c8ba17cb6b80d385cf304dec95f0d0c7e 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 use std::task;
 
 pub fn main() {
index b69644244ab4c49708eae69947a62d70d0c5f68d..7c652ddc406fc9e5d53d46bd371ebf98faed3993 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 use std::task;
 
 fn start(tx: &Sender<int>, i0: int) {
index 5e71ed3ba06eb58871a236fafabf3d8847f26fa0..b7098eb30a3beb708256c9f7afc781d9adfcca57 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::channel;
+use std::sync::mpsc::channel;
 use std::cmp;
 
 // Tests of ports and channels on various types
@@ -17,9 +17,9 @@ struct R {val0: int, val1: u8, val2: char}
 
     let (tx, rx) = channel();
     let r0: R = R {val0: 0, val1: 1u8, val2: '2'};
-    tx.send(r0);
+    tx.send(r0).unwrap();
     let mut r1: R;
-    r1 = rx.recv();
+    r1 = rx.recv().unwrap();
     assert_eq!(r1.val0, 0);
     assert_eq!(r1.val1, 1u8);
     assert_eq!(r1.val2, '2');
@@ -28,8 +28,8 @@ struct R {val0: int, val1: u8, val2: char}
 fn test_vec() {
     let (tx, rx) = channel();
     let v0: Vec<int> = vec!(0, 1, 2);
-    tx.send(v0);
-    let v1 = rx.recv();
+    tx.send(v0).unwrap();
+    let v1 = rx.recv().unwrap();
     assert_eq!(v1[0], 0);
     assert_eq!(v1[1], 1);
     assert_eq!(v1[2], 2);
@@ -38,8 +38,8 @@ fn test_vec() {
 fn test_str() {
     let (tx, rx) = channel();
     let s0 = "test".to_string();
-    tx.send(s0);
-    let s1 = rx.recv();
+    tx.send(s0).unwrap();
+    let s1 = rx.recv().unwrap();
     assert_eq!(s1.as_bytes()[0], 't' as u8);
     assert_eq!(s1.as_bytes()[1], 'e' as u8);
     assert_eq!(s1.as_bytes()[2], 's' as u8);
@@ -82,28 +82,28 @@ fn ne(&self, other: &t) -> bool { !(*self).eq(other) }
 
 fn test_tag() {
     let (tx, rx) = channel();
-    tx.send(t::tag1);
-    tx.send(t::tag2(10));
-    tx.send(t::tag3(10, 11u8, 'A'));
+    tx.send(t::tag1).unwrap();
+    tx.send(t::tag2(10)).unwrap();
+    tx.send(t::tag3(10, 11u8, 'A')).unwrap();
     let mut t1: t;
-    t1 = rx.recv();
+    t1 = rx.recv().unwrap();
     assert_eq!(t1, t::tag1);
-    t1 = rx.recv();
+    t1 = rx.recv().unwrap();
     assert_eq!(t1, t::tag2(10));
-    t1 = rx.recv();
+    t1 = rx.recv().unwrap();
     assert_eq!(t1, t::tag3(10, 11u8, 'A'));
 }
 
 fn test_chan() {
     let (tx1, rx1) = channel();
     let (tx2, rx2) = channel();
-    tx1.send(tx2);
-    let tx2 = rx1.recv();
+    tx1.send(tx2).unwrap();
+    let tx2 = rx1.recv().unwrap();
     // Does the transmitted channel still work?
 
-    tx2.send(10);
+    tx2.send(10).unwrap();
     let mut i: int;
-    i = rx2.recv();
+    i = rx2.recv().unwrap();
     assert_eq!(i, 10);
 }
 
index c7a6da6a79417354e0240bd0bc537f911cf12e50..a002a597481e42ee8a660694f223efa37716037c 100644 (file)
@@ -11,7 +11,7 @@
 // no-pretty-expanded FIXME #15189
 
 use std::thread::Thread;
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 
 pub fn main() { println!("===== WITHOUT THREADS ====="); test00(); }
 
@@ -20,7 +20,7 @@ fn test00_start(ch: &Sender<int>, message: int, count: int) {
     let mut i: int = 0;
     while i < count {
         println!("Sending Message");
-        ch.send(message + 0);
+        ch.send(message + 0).unwrap();
         i = i + 1;
     }
     println!("Ending test00_start");
@@ -54,7 +54,7 @@ fn test00() {
     for _r in results.iter() {
         i = 0;
         while i < number_of_messages {
-            let value = rx.recv();
+            let value = rx.recv().unwrap();
             sum += value;
             i = i + 1;
         }
index 0e75479046be665ba6650546574e46089d81f27b..1f1b750aa5727fd63ad51d39185a840a227df769 100644 (file)
@@ -10,7 +10,7 @@
 
 #![allow(dead_assignment)]
 
-use std::comm::channel;
+use std::sync::mpsc::channel;
 
 pub fn main() { test00(); }
 
@@ -18,36 +18,36 @@ fn test00() {
     let mut r: int = 0;
     let mut sum: int = 0;
     let (tx, rx) = channel();
-    tx.send(1);
-    tx.send(2);
-    tx.send(3);
-    tx.send(4);
-    r = rx.recv();
+    tx.send(1).unwrap();
+    tx.send(2).unwrap();
+    tx.send(3).unwrap();
+    tx.send(4).unwrap();
+    r = rx.recv().unwrap();
     sum += r;
     println!("{}", r);
-    r = rx.recv();
+    r = rx.recv().unwrap();
     sum += r;
     println!("{}", r);
-    r = rx.recv();
+    r = rx.recv().unwrap();
     sum += r;
     println!("{}", r);
-    r = rx.recv();
+    r = rx.recv().unwrap();
     sum += r;
     println!("{}", r);
-    tx.send(5);
-    tx.send(6);
-    tx.send(7);
-    tx.send(8);
-    r = rx.recv();
+    tx.send(5).unwrap();
+    tx.send(6).unwrap();
+    tx.send(7).unwrap();
+    tx.send(8).unwrap();
+    r = rx.recv().unwrap();
     sum += r;
     println!("{}", r);
-    r = rx.recv();
+    r = rx.recv().unwrap();
     sum += r;
     println!("{}", r);
-    r = rx.recv();
+    r = rx.recv().unwrap();
     sum += r;
     println!("{}", r);
-    r = rx.recv();
+    r = rx.recv().unwrap();
     sum += r;
     println!("{}", r);
     assert_eq!(sum, 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8);
index d4edbf85cd833830a270a587cbf403ae2fb476ed..039308d5cfed736c903f87f5ff4bc4248e811bdc 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::channel;
+use std::sync::mpsc::channel;
 
 pub fn main() { test00(); }
 
@@ -18,8 +18,8 @@ fn test00() {
     let (tx, rx) = channel();
     let number_of_messages: int = 1000;
     let mut i: int = 0;
-    while i < number_of_messages { tx.send(i + 0); i += 1; }
+    while i < number_of_messages { tx.send(i + 0).unwrap(); i += 1; }
     i = 0;
-    while i < number_of_messages { sum += rx.recv(); i += 1; }
+    while i < number_of_messages { sum += rx.recv().unwrap(); i += 1; }
     assert_eq!(sum, number_of_messages * (number_of_messages - 1) / 2);
 }
index 4c18e5dc31357c8f8e9d45a0cf5bec4235b0bf26..7cdfddcdeb113ff4fe3fd2c9ffca3d3aebad30a0 100644 (file)
@@ -10,7 +10,7 @@
 
 #![allow(dead_assignment)]
 
-use std::comm::channel;
+use std::sync::mpsc::channel;
 
 pub fn main() { test00(); }
 
@@ -25,21 +25,21 @@ fn test00() {
     let number_of_messages: int = 1000;
     let mut i: int = 0;
     while i < number_of_messages {
-        tx0.send(i + 0);
-        tx1.send(i + 0);
-        tx2.send(i + 0);
-        tx3.send(i + 0);
+        tx0.send(i + 0).unwrap();
+        tx1.send(i + 0).unwrap();
+        tx2.send(i + 0).unwrap();
+        tx3.send(i + 0).unwrap();
         i += 1;
     }
     i = 0;
     while i < number_of_messages {
-        r = rx.recv();
+        r = rx.recv().unwrap();
         sum += r;
-        r = rx.recv();
+        r = rx.recv().unwrap();
         sum += r;
-        r = rx.recv();
+        r = rx.recv().unwrap();
         sum += r;
-        r = rx.recv();
+        r = rx.recv().unwrap();
         sum += r;
         i += 1;
     }
index e7e5c04e1954e80058854699803362a71f9e043e..054090eca390343a0bff0c9f8deaefe33bed4251 100644 (file)
@@ -10,7 +10,7 @@
 
 #![allow(dead_assignment)]
 
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 use std::task;
 
 pub fn main() { test00(); }
@@ -18,7 +18,7 @@
 fn test00_start(c: &Sender<int>, start: int,
                 number_of_messages: int) {
     let mut i: int = 0;
-    while i < number_of_messages { c.send(start + i); i += 1; }
+    while i < number_of_messages { c.send(start + i).unwrap(); i += 1; }
 }
 
 fn test00() {
@@ -46,13 +46,13 @@ fn test00() {
 
     let mut i: int = 0;
     while i < number_of_messages {
-        r = rx.recv();
+        r = rx.recv().unwrap();
         sum += r;
-        r = rx.recv();
+        r = rx.recv().unwrap();
         sum += r;
-        r = rx.recv();
+        r = rx.recv().unwrap();
         sum += r;
-        r = rx.recv();
+        r = rx.recv().unwrap();
         sum += r;
         i += 1;
     }
index 5a271f9dc05fd70e4cf3942a8436f8b51f80c875..d9faf6ee4e4b24a0a1dce1f2a43c41ae36b854ec 100644 (file)
@@ -9,13 +9,13 @@
 // except according to those terms.
 
 use std::thread::Thread;
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 
 pub fn main() { test00(); }
 
 fn test00_start(c: &Sender<int>, number_of_messages: int) {
     let mut i: int = 0;
-    while i < number_of_messages { c.send(i + 0); i += 1; }
+    while i < number_of_messages { c.send(i + 0).unwrap(); i += 1; }
 }
 
 fn test00() {
@@ -30,7 +30,7 @@ fn test00() {
 
     let mut i: int = 0;
     while i < number_of_messages {
-        sum += rx.recv();
+        sum += rx.recv().unwrap();
         println!("{}", r);
         i += 1;
     }
index 368cac1d27dfa130da10a930796d9e4401923290..78a42632001d0dec1208b3c5022724e79982071f 100644 (file)
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::channel;
+use std::sync::mpsc::channel;
 
 // rustboot can't transmit nils across channels because they don't have
 // any size, but rustc currently can because they do have size. Whether
 // or not this is desirable I don't know, but here's a regression test.
 pub fn main() {
     let (tx, rx) = channel();
-    tx.send(());
-    let n: () = rx.recv();
+    tx.send(()).unwrap();
+    let n: () = rx.recv().unwrap();
     assert_eq!(n, ());
 }
index 1e10a4186fba9940030a0b521b31e9f95c97af20..623a30eda1a4bc54b737232575796b5e464290c1 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::task;
-use std::comm::channel;
+use std::sync::mpsc::channel;
 
 pub fn main() {
     let (tx, rx) = channel::<uint>();
@@ -19,9 +19,9 @@ pub fn main() {
 
     task::spawn(move || {
         let x_in_child = &(*x) as *const int as uint;
-        tx.send(x_in_child);
+        tx.send(x_in_child).unwrap();
     });
 
-    let x_in_child = rx.recv();
+    let x_in_child = rx.recv().unwrap();
     assert_eq!(x_in_parent, x_in_child);
 }
index 048d7b2be72253b7456730fecfc52bf2bca970fc..a7eabe0edb3845468dc07836eb5f4086c82e4c62 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::channel;
+use std::sync::mpsc::channel;
 use std::io::{ChanReader, ChanWriter};
 use std::thread;
 
index 8f5a45cd1dd8c4f0e3940e9c76ffe3221b983e22..07f71fe580e9fdd52c1244ca2b20e05e9ec2b700 100644 (file)
@@ -13,7 +13,7 @@
 //              quite quickly and it takes a few seconds for the sockets to get
 //              recycled.
 
-use std::comm::channel;
+use std::sync::mpsc::channel;
 use std::io::{TcpListener, Listener, Acceptor, EndOfFile, TcpStream};
 use std::sync::{atomic, Arc};
 use std::thread::Thread;
index e098e7e96ec6a4e8d8c4e952eaa1ce007791b209..c33bdcf86980118dfacf8bda2f43924e62036a1e 100644 (file)
@@ -27,7 +27,7 @@
 use std::io::test::*;
 use std::io;
 use std::time::Duration;
-use std::comm::channel;
+use std::sync::mpsc::channel;
 
 #[cfg_attr(target_os = "freebsd", ignore)]
 fn eventual_timeout() {
@@ -37,10 +37,10 @@ fn eventual_timeout() {
     let (_tx2, rx2) = channel::<()>();
     std::task::spawn(move|| {
         let _l = TcpListener::bind(addr).unwrap().listen();
-        tx1.send(());
-        let _ = rx2.recv_opt();
+        tx1.send(()).unwrap();
+        let _ = rx2.recv();
     });
-    rx1.recv();
+    rx1.recv().unwrap();
 
     let mut v = Vec::new();
     for _ in range(0u, 10000) {
index 4fcdf49d971a164d3223fe247a2eca10b116f631..9e67095bb3031856e5faef1c83c67c08764d693f 100644 (file)
@@ -23,7 +23,7 @@
 use std::io;
 use std::os;
 use std::task;
-use std::comm::channel;
+use std::sync::mpsc::channel;
 
 fn test_tempdir() {
     let path = {
@@ -39,11 +39,11 @@ fn test_rm_tempdir() {
     let (tx, rx) = channel();
     let f = move|:| -> () {
         let tmp = TempDir::new("test_rm_tempdir").unwrap();
-        tx.send(tmp.path().clone());
+        tx.send(tmp.path().clone()).unwrap();
         panic!("panic to unwind past `tmp`");
     };
     task::try(f);
-    let path = rx.recv();
+    let path = rx.recv().unwrap();
     assert!(!path.exists());
 
     let tmp = TempDir::new("test_rm_tempdir").unwrap();
@@ -80,12 +80,12 @@ fn test_rm_tempdir_close() {
     let (tx, rx) = channel();
     let f = move|:| -> () {
         let tmp = TempDir::new("test_rm_tempdir").unwrap();
-        tx.send(tmp.path().clone());
+        tx.send(tmp.path().clone()).unwrap();
         tmp.close();
         panic!("panic when unwinding past `tmp`");
     };
     task::try(f);
-    let path = rx.recv();
+    let path = rx.recv().unwrap();
     assert!(!path.exists());
 
     let tmp = TempDir::new("test_rm_tempdir").unwrap();
index dd16514d83a61ad6a38224b4793b98105f982b96..0d2cb60c213c112083226d27884a85339f6c040f 100644 (file)
@@ -12,7 +12,7 @@
 // and shared between tasks as long as all types fulfill Send.
 
 use std::sync::Arc;
-use std::comm::channel;
+use std::sync::mpsc::channel;
 use std::task;
 
 trait Pet {
index 1ff3ba3106b377235fb7a56a471106760c96438d..6bece8265c0066252f3f68752a86181b49d8dd0a 100644 (file)
@@ -13,7 +13,7 @@
   message.
  */
 
-use std::comm::channel;
+use std::sync::mpsc::channel;
 
 pub fn main() {
     let (tx, rx) = channel();
index e66c8730898f8edfde855263b390d12c6369c823..f88c458f2ed76d235c480c01fbf4a00050573037 100644 (file)
@@ -9,10 +9,10 @@
 // except according to those terms.
 
 use std::task;
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 
 fn child(tx: &Sender<Box<uint>>, i: uint) {
-    tx.send(box i);
+    tx.send(box i).unwrap();
 }
 
 pub fn main() {
@@ -29,7 +29,7 @@ pub fn main() {
 
     let mut actual = 0u;
     for _ in range(0u, n) {
-        let j = rx.recv();
+        let j = rx.recv().unwrap();
         actual += *j;
     }
 
index 0a661a51bf16cc98c4dba94bd815135fae5b0757..afafb204c1c9f7072e5093fc20cb335422928eba 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::channel;
+use std::sync::mpsc::channel;
 
 pub fn main() {
     let (tx, rx) = channel();
-    tx.send(box 100i);
-    let v = rx.recv();
+    tx.send(box 100i).unwrap();
+    let v = rx.recv().unwrap();
     assert_eq!(v, box 100i);
 }
index 1284c938d55402dddae3c75b158786b67c87b9e7..943b2d3edd12ee9be9e71c6ae48a883ba78a7b99 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::comm::{channel, Sender};
+use std::sync::mpsc::{channel, Sender};
 use std::task;
 
 struct complainer {
@@ -18,7 +18,7 @@ struct complainer {
 impl Drop for complainer {
     fn drop(&mut self) {
         println!("About to send!");
-        self.tx.send(true);
+        self.tx.send(true).unwrap();
         println!("Sent!");
     }
 }
@@ -39,5 +39,5 @@ pub fn main() {
     let (tx, rx) = channel();
     task::spawn(move|| f(tx.clone()));
     println!("hiiiiiiiii");
-    assert!(rx.recv());
+    assert!(rx.recv().unwrap());
 }