about summary refs log tree commit diff
path: root/src/libstd/comm
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-04-16 16:31:29 -0700
committerbors <bors@rust-lang.org>2014-04-16 16:31:29 -0700
commitccccbd23680f317509a14ed7a4abb7f1969e78ae (patch)
treeb16d0ec3e740b2b9494615784b19d9287cf3d1b0 /src/libstd/comm
parent8dc935e42c6efbc026a0b89080376684ec8e03fc (diff)
parentd1bfa51ea86259de21665077e4d32f8f8322b8e1 (diff)
downloadrust-ccccbd23680f317509a14ed7a4abb7f1969e78ae.tar.gz
rust-ccccbd23680f317509a14ed7a4abb7f1969e78ae.zip
auto merge of #13465 : alexcrichton/rust/fix-comm-dox, r=brson
Some of this documentation got a little out of date. There was no mention of a
`SyncSender`, and the entire "Outside the runtime" section isn't really true any
more (or really all that relevant).

This also updates a few other doc blocks and adds some examples.
Diffstat (limited to 'src/libstd/comm')
-rw-r--r--src/libstd/comm/mod.rs100
1 files changed, 77 insertions, 23 deletions
diff --git a/src/libstd/comm/mod.rs b/src/libstd/comm/mod.rs
index e2d7a869fbc..7700000b869 100644
--- a/src/libstd/comm/mod.rs
+++ b/src/libstd/comm/mod.rs
@@ -16,19 +16,32 @@
 //! module are the building blocks for synchronization in rust.
 //!
 //! This module provides message-based communication over channels, concretely
-//! defined as two types:
+//! defined among three types:
 //!
 //! * `Sender`
+//! * `SyncSender`
 //! * `Receiver`
 //!
-//! A `Sender` is used to send data to a `Receiver`. A `Sender` is 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.
+//! 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 can be used as if they have an infinite internal buffer. What
-//! this means is that the `send` operation will never block. `Receiver`s, on
-//! the other hand, will block the task if there is no data to be received.
+//! 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.
 //!
 //! ## Failure Propagation
 //!
@@ -38,32 +51,40 @@
 //! `fail!`. The purpose of this is to allow propagation of failure among tasks
 //! that are linked to one another via channels.
 //!
-//! There are methods on both of `Sender` and `Receiver` to perform their
+//! There are methods on both of senders and receivers to perform their
 //! respective operations without failing, however.
 //!
-//! ## Outside the Runtime
+//! ## Runtime Requirements
 //!
-//! All channels and ports work seamlessly inside and outside of the rust
-//! runtime. This means that code may use channels to communicate information
-//! inside and outside of the runtime. For example, if rust were embedded as an
-//! FFI module in another application, the rust runtime would probably be
-//! running in its own external thread pool. Channels created can communicate
-//! from the native application threads to the rust threads through the use of
-//! native mutexes and condition variables.
+//! The channel types defined in this module generally have very few runtime
+//! requirements in order to operate. The major requirement they have is for a
+//! local rust `Task` to be available if any *blocking* operation is performed.
 //!
-//! What this means is that if a native thread is using a channel, execution
-//! will be blocked accordingly by blocking the OS thread.
+//! If a local `Task` is not available (for example an FFI callback), then the
+//! `send` operation is safe on a `Sender` (as well as a `send_opt`) as well as
+//! the `try_send` method on a `SyncSender`, but no other operations are
+//! guaranteed to be safe.
+//!
+//! Additionally, channels can interoperate between runtimes. If one task in a
+//! program is running on libnative and another is running on libgreen, they can
+//! still communicate with one another using channels.
 //!
 //! # Example
 //!
-//! ```rust,should_fail
+//! Simple usage:
+//!
+//! ```
 //! // Create a simple streaming channel
 //! let (tx, rx) = channel();
 //! spawn(proc() {
 //!     tx.send(10);
 //! });
 //! assert_eq!(rx.recv(), 10);
+//! ```
+//!
+//! Shared usage:
 //!
+//! ```
 //! // Create a shared channel which can be sent along from many tasks
 //! let (tx, rx) = channel();
 //! for i in range(0, 10) {
@@ -77,13 +98,28 @@
 //!     let j = rx.recv();
 //!     assert!(0 <= j && j < 10);
 //! }
+//! ```
 //!
+//! Propagating failure:
+//!
+//! ```should_fail
 //! // The call to recv() will fail!() because the channel has already hung
 //! // up (or been deallocated)
 //! let (tx, rx) = channel::<int>();
 //! drop(tx);
 //! rx.recv();
 //! ```
+//!
+//! Synchronous channels:
+//!
+//! ```
+//! let (tx, rx) = sync_channel(0);
+//! spawn(proc() {
+//!     // This will wait for the parent task to start receiving
+//!     tx.send(53);
+//! });
+//! rx.recv();
+//! ```
 
 // A description of how Rust's channel implementation works
 //
@@ -354,9 +390,27 @@ enum Flavor<T> {
     Sync(UnsafeArc<sync::Packet<T>>),
 }
 
-/// Creates a new channel, returning the sender/receiver halves. All data sent
-/// on the sender will become available on the receiver. See the documentation
-/// of `Receiver` and `Sender` to see what's possible with them.
+/// 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
+///
+/// ```
+/// let (tx, rx) = channel();
+///
+/// // Spawn off an expensive computation
+/// spawn(proc() {
+/// #   fn expensive_computation() {}
+///     tx.send(expensive_computation());
+/// });
+///
+/// // Do some useful work for awhile
+///
+/// // Let's see what that answer was
+/// println!("{}", rx.recv());
+/// ```
 pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
     let (a, b) = UnsafeArc::new2(oneshot::Packet::new());
     (Sender::new(Oneshot(b)), Receiver::new(Oneshot(a)))