Skip to content

Commit 66b9d34

Browse files
committed
---
yaml --- r: 23284 b: refs/heads/master c: b206920 h: refs/heads/master v: v3
1 parent 6869f64 commit 66b9d34

File tree

2 files changed

+48
-60
lines changed

2 files changed

+48
-60
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 924e787119969c740911d0d1aaf28ab19b77c1a2
2+
refs/heads/master: b206920d9d8c46ee38d3d3930afc57d2a0cfb3f7
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: cd6f24f9d14ac90d167386a56e7a6ac1f0318195
55
refs/heads/try: ffbe0e0e00374358b789b0037bcb3a577cd218be

trunk/doc/tutorial.md

Lines changed: 47 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2882,21 +2882,20 @@ arguments and generates no return value. The effect of `task::spawn()`
28822882
is to fire up a child task that will execute the closure in parallel
28832883
with the creator.
28842884

2885-
## Ports and channels
2885+
## Communication
28862886

28872887
Now that we have spawned a child task, it would be nice if we could
2888-
communicate with it. This is done by creating a *port* with an
2889-
associated *channel*. A port is simply a location to receive messages
2890-
of a particular type. A channel is used to send messages to a port.
2891-
For example, imagine we wish to perform two expensive computations
2892-
in parallel. We might write something like:
2888+
communicate with it. This is done using *pipes*. Pipes are simply a
2889+
pair of endpoints, with one for sending messages and another for
2890+
receiving messages. The easiest way to create a pipe is to use
2891+
`pipes::stream`. Imagine we wish to perform two expensive
2892+
computations in parallel. We might write something like:
28932893

28942894
~~~~
28952895
import task::spawn;
2896-
import comm::{port, chan};
2896+
import pipes::{stream, port, chan};
28972897
2898-
let port = port();
2899-
let chan = port.chan();
2898+
let (chan, port) = stream();
29002899
29012900
do spawn {
29022901
let result = some_expensive_computation();
@@ -2911,25 +2910,16 @@ let result = port.recv();
29112910
~~~~
29122911

29132912
Let's walk through this code line-by-line. The first line creates a
2914-
port for receiving integers:
2913+
stream for sending and receiving integers:
29152914

29162915
~~~~ {.ignore}
2917-
# import comm::port;
2918-
let port = port();
2916+
# import pipes::stream;
2917+
let (chan, port) = stream();
29192918
~~~~
29202919

29212920
This port is where we will receive the message from the child task
2922-
once it is complete. The second line creates a channel for sending
2923-
integers to the port `port`:
2924-
2925-
~~~~
2926-
# import comm::{port, chan};
2927-
# let port = port::<int>();
2928-
let chan = port.chan();
2929-
~~~~
2930-
2931-
The channel will be used by the child to send a message to the port.
2932-
The next statement actually spawns the child:
2921+
once it is complete. The channel will be used by the child to send a
2922+
message to the port. The next statement actually spawns the child:
29332923

29342924
~~~~
29352925
# import task::{spawn};
@@ -2953,10 +2943,9 @@ some other expensive computation and then waiting for the child's result
29532943
to arrive on the port:
29542944

29552945
~~~~
2956-
# import comm::{port, chan};
2946+
# import pipes::{stream, port, chan};
29572947
# fn some_other_expensive_computation() {}
2958-
# let port = port::<int>();
2959-
# let chan = chan::<int>(port);
2948+
# let (chan, port) = stream::<int>();
29602949
# chan.send(0);
29612950
some_other_expensive_computation();
29622951
let result = port.recv();
@@ -2965,74 +2954,73 @@ let result = port.recv();
29652954
## Creating a task with a bi-directional communication path
29662955

29672956
A very common thing to do is to spawn a child task where the parent
2968-
and child both need to exchange messages with each
2969-
other. The function `task::spawn_conversation()` supports this pattern.
2970-
We'll look briefly at how it is used.
2957+
and child both need to exchange messages with each other. There
2958+
function `std::comm::DuplexStream()` supports this pattern. We'll
2959+
look briefly at how it is used.
29712960

29722961
To see how `spawn_conversation()` works, we will create a child task
29732962
that receives `uint` messages, converts them to a string, and sends
29742963
the string in response. The child terminates when `0` is received.
29752964
Here is the function that implements the child task:
29762965

29772966
~~~~
2978-
# import comm::{Port, port, Chan, chan};
2979-
fn stringifier(from_parent: Port<uint>,
2980-
to_parent: Chan<~str>) {
2967+
# import std::comm::DuplexStream;
2968+
# import pipes::{port, chan};
2969+
fn stringifier(channel: DuplexStream<~str, uint>) {
29812970
let mut value: uint;
29822971
loop {
2983-
value = from_parent.recv();
2984-
to_parent.send(uint::to_str(value, 10u));
2972+
value = channel.recv();
2973+
channel.send(uint::to_str(value, 10u));
29852974
if value == 0u { break; }
29862975
}
29872976
}
29882977
~~~~
29892978

2990-
You can see that the function takes two parameters. The first is a
2991-
port used to receive messages from the parent, and the second is a
2992-
channel used to send messages to the parent. The body itself simply
2993-
loops, reading from the `from_parent` port and then sending its
2994-
response to the `to_parent` channel. The actual response itself is
2995-
simply the strified version of the received value,
2979+
The implementation of `DuplexStream` supports both sending and
2980+
receiving. The `stringifier` function takes a `DuplexStream` that can
2981+
send strings (the first type parameter) and receive `uint` messages
2982+
(the second type parameter). The body itself simply loops, reading
2983+
from the channel and then sending its response back. The actual
2984+
response itself is simply the strified version of the received value,
29962985
`uint::to_str(value)`.
29972986

29982987
Here is the code for the parent task:
29992988

30002989
~~~~
3001-
# import task::{spawn_conversation};
3002-
# import comm::{Chan, chan, Port, port};
3003-
# fn stringifier(from_parent: comm::Port<uint>,
3004-
# to_parent: comm::Chan<~str>) {
3005-
# comm::send(to_parent, ~"22");
3006-
# comm::send(to_parent, ~"23");
3007-
# comm::send(to_parent, ~"0");
2990+
# import std::comm::DuplexStream;
2991+
# import pipes::{port, chan};
2992+
# import task::spawn;
2993+
# fn stringifier(channel: DuplexStream<~str, uint>) {
2994+
# let mut value: uint;
2995+
# loop {
2996+
# value = channel.recv();
2997+
# channel.send(uint::to_str(value, 10u));
2998+
# if value == 0u { break; }
2999+
# }
30083000
# }
30093001
# fn main() {
30103002
3011-
let (from_child, to_child) = do spawn_conversation |from_parent, to_parent| {
3012-
stringifier(from_parent, to_parent);
3003+
let (from_child, to_child) = DuplexStream();
3004+
3005+
do spawn |to_child| {
3006+
stringifier();
30133007
};
30143008
3015-
to_child.send(22u);
3009+
from_child.send(22u);
30163010
assert from_child.recv() == ~"22";
30173011
3018-
to_child.send(23u);
3019-
to_child.send(0u);
3012+
from_child.send(23u);
3013+
from_child.send(0u);
30203014
30213015
assert from_child.recv() == ~"23";
30223016
assert from_child.recv() == ~"0";
30233017
30243018
# }
30253019
~~~~
30263020

3027-
The parent task calls `spawn_conversation` with a function that takes
3028-
a `from_parent` port and a `to_parent` channel. In return, it gets a
3029-
`from_child` channel and a `to_child` port. As a result, both parent
3021+
The parent task first calls `DuplexStream` to create a pair of bidirectional endpoints. It then uses `task::spawn` to create the child task, which captures one end of the communication channel. As a result, both parent
30303022
and child can send and receive data to and from the other.
30313023

3032-
`spawn_conversation`
3033-
will create two port/channel pairs, passing one set to the child task
3034-
and returning the other set to the caller.
3035-
30363024
# Testing
30373025

30383026
The Rust language has a facility for testing built into the language.

0 commit comments

Comments
 (0)