std: Update documentation on the comm
module
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.
This commit is contained in:
parent
ab0d847277
commit
d1bfa51ea8
@ -16,19 +16,32 @@
|
|||||||
//! module are the building blocks for synchronization in rust.
|
//! module are the building blocks for synchronization in rust.
|
||||||
//!
|
//!
|
||||||
//! This module provides message-based communication over channels, concretely
|
//! This module provides message-based communication over channels, concretely
|
||||||
//! defined as two types:
|
//! defined among three types:
|
||||||
//!
|
//!
|
||||||
//! * `Sender`
|
//! * `Sender`
|
||||||
|
//! * `SyncSender`
|
||||||
//! * `Receiver`
|
//! * `Receiver`
|
||||||
//!
|
//!
|
||||||
//! A `Sender` is used to send data to a `Receiver`. A `Sender` is clone-able
|
//! A `Sender` or `SyncSender` is used to send data to a `Receiver`. Both
|
||||||
//! such that many tasks can send simultaneously to one receiver. These
|
//! senders are clone-able such that many tasks can send simultaneously to one
|
||||||
//! channels are *task blocking*, not *thread blocking*. This means that if one
|
//! receiver. These channels are *task blocking*, not *thread blocking*. This
|
||||||
//! task is blocked on a channel, other tasks can continue to make progress.
|
//! 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
|
//! Rust channels come in one of two flavors:
|
||||||
//! 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.
|
//! 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
|
//! ## Failure Propagation
|
||||||
//!
|
//!
|
||||||
@ -38,32 +51,40 @@
|
|||||||
//! `fail!`. The purpose of this is to allow propagation of failure among tasks
|
//! `fail!`. The purpose of this is to allow propagation of failure among tasks
|
||||||
//! that are linked to one another via channels.
|
//! 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.
|
//! respective operations without failing, however.
|
||||||
//!
|
//!
|
||||||
//! ## Outside the Runtime
|
//! ## Runtime Requirements
|
||||||
//!
|
//!
|
||||||
//! All channels and ports work seamlessly inside and outside of the rust
|
//! The channel types defined in this module generally have very few runtime
|
||||||
//! runtime. This means that code may use channels to communicate information
|
//! requirements in order to operate. The major requirement they have is for a
|
||||||
//! inside and outside of the runtime. For example, if rust were embedded as an
|
//! local rust `Task` to be available if any *blocking* operation is performed.
|
||||||
//! 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.
|
|
||||||
//!
|
//!
|
||||||
//! What this means is that if a native thread is using a channel, execution
|
//! If a local `Task` is not available (for example an FFI callback), then the
|
||||||
//! will be blocked accordingly by blocking the OS thread.
|
//! `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
|
//! # Example
|
||||||
//!
|
//!
|
||||||
//! ```rust,should_fail
|
//! Simple usage:
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
//! // Create a simple streaming channel
|
//! // Create a simple streaming channel
|
||||||
//! let (tx, rx) = channel();
|
//! let (tx, rx) = channel();
|
||||||
//! spawn(proc() {
|
//! spawn(proc() {
|
||||||
//! tx.send(10);
|
//! tx.send(10);
|
||||||
//! });
|
//! });
|
||||||
//! assert_eq!(rx.recv(), 10);
|
//! assert_eq!(rx.recv(), 10);
|
||||||
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
//! Shared usage:
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
//! // Create a shared channel which can be sent along from many tasks
|
//! // Create a shared channel which can be sent along from many tasks
|
||||||
//! let (tx, rx) = channel();
|
//! let (tx, rx) = channel();
|
||||||
//! for i in range(0, 10) {
|
//! for i in range(0, 10) {
|
||||||
@ -77,13 +98,28 @@
|
|||||||
//! let j = rx.recv();
|
//! let j = rx.recv();
|
||||||
//! assert!(0 <= j && j < 10);
|
//! assert!(0 <= j && j < 10);
|
||||||
//! }
|
//! }
|
||||||
|
//! ```
|
||||||
//!
|
//!
|
||||||
|
//! Propagating failure:
|
||||||
|
//!
|
||||||
|
//! ```should_fail
|
||||||
//! // The call to recv() will fail!() because the channel has already hung
|
//! // The call to recv() will fail!() because the channel has already hung
|
||||||
//! // up (or been deallocated)
|
//! // up (or been deallocated)
|
||||||
//! let (tx, rx) = channel::<int>();
|
//! let (tx, rx) = channel::<int>();
|
||||||
//! drop(tx);
|
//! drop(tx);
|
||||||
//! rx.recv();
|
//! 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
|
// A description of how Rust's channel implementation works
|
||||||
//
|
//
|
||||||
@ -354,9 +390,27 @@ enum Flavor<T> {
|
|||||||
Sync(UnsafeArc<sync::Packet<T>>),
|
Sync(UnsafeArc<sync::Packet<T>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new channel, returning the sender/receiver halves. All data sent
|
/// Creates a new asynchronous channel, returning the sender/receiver halves.
|
||||||
/// on the sender will become available on the receiver. See the documentation
|
///
|
||||||
/// of `Receiver` and `Sender` to see what's possible with them.
|
/// 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>) {
|
pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
|
||||||
let (a, b) = UnsafeArc::new2(oneshot::Packet::new());
|
let (a, b) = UnsafeArc::new2(oneshot::Packet::new());
|
||||||
(Sender::new(Oneshot(b)), Receiver::new(Oneshot(a)))
|
(Sender::new(Oneshot(b)), Receiver::new(Oneshot(a)))
|
||||||
|
Loading…
Reference in New Issue
Block a user