Skip to content

Commit ccccbd2

Browse files
committed
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.
2 parents 8dc935e + d1bfa51 commit ccccbd2

File tree

1 file changed

+77
-23
lines changed

1 file changed

+77
-23
lines changed

src/libstd/comm/mod.rs

+77-23
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,32 @@
1616
//! module are the building blocks for synchronization in rust.
1717
//!
1818
//! This module provides message-based communication over channels, concretely
19-
//! defined as two types:
19+
//! defined among three types:
2020
//!
2121
//! * `Sender`
22+
//! * `SyncSender`
2223
//! * `Receiver`
2324
//!
24-
//! A `Sender` is used to send data to a `Receiver`. A `Sender` is clone-able
25-
//! such that many tasks can send simultaneously to one receiver. These
26-
//! channels are *task blocking*, not *thread blocking*. This means that if one
27-
//! task is blocked on a channel, other tasks can continue to make progress.
25+
//! A `Sender` or `SyncSender` is used to send data to a `Receiver`. Both
26+
//! senders are clone-able such that many tasks can send simultaneously to one
27+
//! receiver. These channels are *task blocking*, not *thread blocking*. This
28+
//! means that if one task is blocked on a channel, other tasks can continue to
29+
//! make progress.
2830
//!
29-
//! Rust channels can be used as if they have an infinite internal buffer. What
30-
//! this means is that the `send` operation will never block. `Receiver`s, on
31-
//! the other hand, will block the task if there is no data to be received.
31+
//! Rust channels come in one of two flavors:
32+
//!
33+
//! 1. An asynchronous, infinitely buffered channel. The `channel()` function
34+
//! will return a `(Sender, Receiver)` tuple where all sends will be
35+
//! **asynchronous** (they never block). The channel conceptually has an
36+
//! infinite buffer.
37+
//!
38+
//! 2. A synchronous, bounded channel. The `sync_channel()` function will return
39+
//! a `(SyncSender, Receiver)` tuple where the storage for pending messages
40+
//! is a pre-allocated buffer of a fixed size. All sends will be
41+
//! **synchronous** by blocking until there is buffer space available. Note
42+
//! that a bound of 0 is allowed, causing the channel to become a
43+
//! "rendezvous" channel where each sender atomically hands off a message to
44+
//! a receiver.
3245
//!
3346
//! ## Failure Propagation
3447
//!
@@ -38,32 +51,40 @@
3851
//! `fail!`. The purpose of this is to allow propagation of failure among tasks
3952
//! that are linked to one another via channels.
4053
//!
41-
//! There are methods on both of `Sender` and `Receiver` to perform their
54+
//! There are methods on both of senders and receivers to perform their
4255
//! respective operations without failing, however.
4356
//!
44-
//! ## Outside the Runtime
57+
//! ## Runtime Requirements
4558
//!
46-
//! All channels and ports work seamlessly inside and outside of the rust
47-
//! runtime. This means that code may use channels to communicate information
48-
//! inside and outside of the runtime. For example, if rust were embedded as an
49-
//! FFI module in another application, the rust runtime would probably be
50-
//! running in its own external thread pool. Channels created can communicate
51-
//! from the native application threads to the rust threads through the use of
52-
//! native mutexes and condition variables.
59+
//! The channel types defined in this module generally have very few runtime
60+
//! requirements in order to operate. The major requirement they have is for a
61+
//! local rust `Task` to be available if any *blocking* operation is performed.
5362
//!
54-
//! What this means is that if a native thread is using a channel, execution
55-
//! will be blocked accordingly by blocking the OS thread.
63+
//! If a local `Task` is not available (for example an FFI callback), then the
64+
//! `send` operation is safe on a `Sender` (as well as a `send_opt`) as well as
65+
//! the `try_send` method on a `SyncSender`, but no other operations are
66+
//! guaranteed to be safe.
67+
//!
68+
//! Additionally, channels can interoperate between runtimes. If one task in a
69+
//! program is running on libnative and another is running on libgreen, they can
70+
//! still communicate with one another using channels.
5671
//!
5772
//! # Example
5873
//!
59-
//! ```rust,should_fail
74+
//! Simple usage:
75+
//!
76+
//! ```
6077
//! // Create a simple streaming channel
6178
//! let (tx, rx) = channel();
6279
//! spawn(proc() {
6380
//! tx.send(10);
6481
//! });
6582
//! assert_eq!(rx.recv(), 10);
83+
//! ```
84+
//!
85+
//! Shared usage:
6686
//!
87+
//! ```
6788
//! // Create a shared channel which can be sent along from many tasks
6889
//! let (tx, rx) = channel();
6990
//! for i in range(0, 10) {
@@ -77,13 +98,28 @@
7798
//! let j = rx.recv();
7899
//! assert!(0 <= j && j < 10);
79100
//! }
101+
//! ```
80102
//!
103+
//! Propagating failure:
104+
//!
105+
//! ```should_fail
81106
//! // The call to recv() will fail!() because the channel has already hung
82107
//! // up (or been deallocated)
83108
//! let (tx, rx) = channel::<int>();
84109
//! drop(tx);
85110
//! rx.recv();
86111
//! ```
112+
//!
113+
//! Synchronous channels:
114+
//!
115+
//! ```
116+
//! let (tx, rx) = sync_channel(0);
117+
//! spawn(proc() {
118+
//! // This will wait for the parent task to start receiving
119+
//! tx.send(53);
120+
//! });
121+
//! rx.recv();
122+
//! ```
87123
88124
// A description of how Rust's channel implementation works
89125
//
@@ -354,9 +390,27 @@ enum Flavor<T> {
354390
Sync(UnsafeArc<sync::Packet<T>>),
355391
}
356392

357-
/// Creates a new channel, returning the sender/receiver halves. All data sent
358-
/// on the sender will become available on the receiver. See the documentation
359-
/// of `Receiver` and `Sender` to see what's possible with them.
393+
/// Creates a new asynchronous channel, returning the sender/receiver halves.
394+
///
395+
/// All data sent on the sender will become available on the receiver, and no
396+
/// send will block the calling task (this channel has an "infinite buffer").
397+
///
398+
/// # Example
399+
///
400+
/// ```
401+
/// let (tx, rx) = channel();
402+
///
403+
/// // Spawn off an expensive computation
404+
/// spawn(proc() {
405+
/// # fn expensive_computation() {}
406+
/// tx.send(expensive_computation());
407+
/// });
408+
///
409+
/// // Do some useful work for awhile
410+
///
411+
/// // Let's see what that answer was
412+
/// println!("{}", rx.recv());
413+
/// ```
360414
pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
361415
let (a, b) = UnsafeArc::new2(oneshot::Packet::new());
362416
(Sender::new(Oneshot(b)), Receiver::new(Oneshot(a)))

0 commit comments

Comments
 (0)