add section on spawn_connected to tutorial and pull test into file

This commit is contained in:
Niko Matsakis 2012-01-11 09:48:57 -08:00
parent e0cf550527
commit f3b867fd04
3 changed files with 67 additions and 19 deletions

View file

@ -74,3 +74,52 @@ to arrive on the port:
some_other_expensive_computation();
let result = comm::recv(port);
## Creating a task with a bi-directional communication path
A very common thing to do is to spawn a child task where the parent
and child both need to exchange messages with each other. The
function `task::spawn_connected()` supports this pattern. We'll look
briefly at how it is used.
To see how `spawn_connected()` works, we will create a child task
which receives `uint` messages, converts them to a string, and sends
the string in response. The child terminates when `0` is received.
Here is the function which implements the child task:
fn stringifier(from_par: comm::port<uint>,
to_par: comm::chan<str>) {
let value: uint;
do {
value = comm::recv(from_par);
comm::send(to_par, uint::to_str(value, 10u));
} while value != 0u;
}
You can see that the function takes two parameters. The first is a
port used to receive messages from the parent, and the second is a
channel used to send messages to the parent. The body itself simply
loops, reading from the `from_par` port and then sending its response
to the `to_par` channel. The actual response itself is simply the
strified version of the received value, `uint::to_str(value)`.
Here is the code for the parent task:
fn main() {
let t = task::spawn_connected(stringifier);
comm::send(t.to_child, 22u);
assert comm::recv(t.from_child) == "22";
comm::send(t.to_child, 23u);
assert comm::recv(t.from_child) == "23";
comm::send(t.to_child, 0u);
assert comm::recv(t.from_child) == "0";
}
The call to `spawn_connected()` on the first line will instantiate the
various ports and channels and startup the child task. The returned
value, `t`, is a record of type `task::connected_task<uint,str>`. In
addition to the task id of the child, this record defines two fields,
`from_child` and `to_child`, which contain the port and channel
respectively for communicating with the child. Those fields are used
here to send and receive three messages from the child task.

View file

@ -0,0 +1,18 @@
fn stringifier(from_par: comm::port<uint>,
to_par: comm::chan<str>) {
let value: uint;
do {
value = comm::recv(from_par);
comm::send(to_par, uint::to_str(value, 10u));
} while value != 0u;
}
fn main() {
let t = task::spawn_connected(stringifier);
comm::send(t.to_child, 22u);
assert comm::recv(t.from_child) == "22";
comm::send(t.to_child, 23u);
assert comm::recv(t.from_child) == "23";
comm::send(t.to_child, 0u);
assert comm::recv(t.from_child) == "0";
}

View file

@ -57,22 +57,3 @@ fn spawn_polymorphic() {
task::spawn {|| foo(true);};
task::spawn {|| foo(42);};
}
#[test]
fn spawn_connected_stringifier() {
fn stringifer(p: comm::port<uint>, ch: comm::chan<str>) {
let u = 1u;
while u != 0u {
u = comm::recv(p);
comm::send(ch, uint::to_str(u, 10u));
}
}
let ch = task::spawn_connected(stringifer);
comm::send(ch.to_child, 22u);
assert "22" == comm::recv(ch.from_child);
comm::send(ch.to_child, 44u);
assert "44" == comm::recv(ch.from_child);
comm::send(ch.to_child, 0u);
assert "0" == comm::recv(ch.from_child);
}