|
16 | 16 | //! module are the building blocks for synchronization in rust.
|
17 | 17 | //!
|
18 | 18 | //! This module provides message-based communication over channels, concretely
|
19 |
| -//! defined as two types: |
| 19 | +//! defined among three types: |
20 | 20 | //!
|
21 | 21 | //! * `Sender`
|
| 22 | +//! * `SyncSender` |
22 | 23 | //! * `Receiver`
|
23 | 24 | //!
|
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. |
28 | 30 | //!
|
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. |
32 | 45 | //!
|
33 | 46 | //! ## Failure Propagation
|
34 | 47 | //!
|
|
38 | 51 | //! `fail!`. The purpose of this is to allow propagation of failure among tasks
|
39 | 52 | //! that are linked to one another via channels.
|
40 | 53 | //!
|
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 |
42 | 55 | //! respective operations without failing, however.
|
43 | 56 | //!
|
44 |
| -//! ## Outside the Runtime |
| 57 | +//! ## Runtime Requirements |
45 | 58 | //!
|
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. |
53 | 62 | //!
|
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. |
56 | 71 | //!
|
57 | 72 | //! # Example
|
58 | 73 | //!
|
59 |
| -//! ```rust,should_fail |
| 74 | +//! Simple usage: |
| 75 | +//! |
| 76 | +//! ``` |
60 | 77 | //! // Create a simple streaming channel
|
61 | 78 | //! let (tx, rx) = channel();
|
62 | 79 | //! spawn(proc() {
|
63 | 80 | //! tx.send(10);
|
64 | 81 | //! });
|
65 | 82 | //! assert_eq!(rx.recv(), 10);
|
| 83 | +//! ``` |
| 84 | +//! |
| 85 | +//! Shared usage: |
66 | 86 | //!
|
| 87 | +//! ``` |
67 | 88 | //! // Create a shared channel which can be sent along from many tasks
|
68 | 89 | //! let (tx, rx) = channel();
|
69 | 90 | //! for i in range(0, 10) {
|
|
77 | 98 | //! let j = rx.recv();
|
78 | 99 | //! assert!(0 <= j && j < 10);
|
79 | 100 | //! }
|
| 101 | +//! ``` |
80 | 102 | //!
|
| 103 | +//! Propagating failure: |
| 104 | +//! |
| 105 | +//! ```should_fail |
81 | 106 | //! // The call to recv() will fail!() because the channel has already hung
|
82 | 107 | //! // up (or been deallocated)
|
83 | 108 | //! let (tx, rx) = channel::<int>();
|
84 | 109 | //! drop(tx);
|
85 | 110 | //! rx.recv();
|
86 | 111 | //! ```
|
| 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 | +//! ``` |
87 | 123 |
|
88 | 124 | // A description of how Rust's channel implementation works
|
89 | 125 | //
|
@@ -354,9 +390,27 @@ enum Flavor<T> {
|
354 | 390 | Sync(UnsafeArc<sync::Packet<T>>),
|
355 | 391 | }
|
356 | 392 |
|
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 | +/// ``` |
360 | 414 | pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
|
361 | 415 | let (a, b) = UnsafeArc::new2(oneshot::Packet::new());
|
362 | 416 | (Sender::new(Oneshot(b)), Receiver::new(Oneshot(a)))
|
|
0 commit comments