Permalink
Browse files

core: New task API

  • Loading branch information...
1 parent fbc95ba commit 4220dcf1e9de2c2d2c329ecefa80108b63a69145 @brson brson committed Feb 19, 2012
Showing with 959 additions and 765 deletions.
  1. +40 −44 doc/tutorial.md
  2. +0 −2 src/comp/driver/rustc.rs
  3. +2 −2 src/compiletest/procsrv.rs
  4. +5 −3 src/libcore/comm.rs
  5. +767 −416 src/libcore/task.rs
  6. +2 −8 src/libcore/vec.rs
  7. +6 −14 src/libstd/test.rs
  8. +9 −0 src/rt/rust_builtin.cpp
  9. +14 −8 src/test/bench/msgsend.rs
  10. +5 −3 src/test/bench/shootout-pfib.rs
  11. +1 −1 src/test/bench/shootout-threadring.rs
  12. +1 −1 src/test/bench/task-perf-spawnalot.rs
  13. +11 −9 src/test/bench/task-perf-word-count.rs
  14. +0 −11 src/test/run-pass/binops.rs
  15. +2 −6 src/test/run-pass/issue-507.rs
  16. +3 −2 src/test/run-pass/issue-783.rs
  17. +0 −15 src/test/run-pass/join.rs
  18. +0 −21 src/test/run-pass/linked-failure.rs
  19. +3 −2 src/test/run-pass/lots-a-fail.rs
  20. +1 −1 src/test/run-pass/morestack5.rs
  21. +1 −1 src/test/run-pass/morestack6.rs
  22. +3 −2 src/test/run-pass/send-iloop.rs
  23. +0 −9 src/test/run-pass/spawn-module-qualified.rs
  24. +1 −2 src/test/run-pass/spawn.rs
  25. +1 −7 src/test/run-pass/task-comm-1.rs
  26. +4 −2 src/test/run-pass/task-comm-12.rs
  27. +1 −2 src/test/run-pass/task-comm-13.rs
  28. +0 −31 src/test/run-pass/task-comm-2.rs
  29. +7 −5 src/test/run-pass/task-comm-3.rs
  30. +14 −22 src/test/run-pass/task-comm-7.rs
  31. +0 −51 src/test/run-pass/task-comm-8.rs
  32. +5 −3 src/test/run-pass/task-comm-9.rs
  33. +11 −9 src/test/run-pass/task-comm.rs
  34. +12 −14 src/test/run-pass/task-killjoin.rs
  35. +0 −18 src/test/run-pass/task-spawn-connected.rs
  36. +4 −4 src/test/run-pass/terminate-in-initializer.rs
  37. +3 −2 src/test/run-pass/too-much-recursion.rs
  38. +3 −2 src/test/run-pass/unwind-box.rs
  39. +3 −2 src/test/run-pass/unwind-resource.rs
  40. +3 −2 src/test/run-pass/unwind-resource2.rs
  41. +3 −2 src/test/run-pass/unwind-unique.rs
  42. +4 −2 src/test/run-pass/yield.rs
  43. +4 −2 src/test/run-pass/yield1.rs
View
@@ -2375,10 +2375,10 @@ module `task`. Let's begin with the simplest one, `task::spawn()`:
~~~~
let some_value = 22;
-let child_task = task::spawn {||
+task::spawn {||
std::io::println("This executes in the child task.");
std::io::println(#fmt("%d", some_value));
-};
+}
~~~~
The argument to `task::spawn()` is a [unique
@@ -2456,70 +2456,66 @@ 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.
+and child both need to exchange messages with each
+other. The function `task::spawn_listener()` supports this pattern. We'll look
+briefly at how it is used.
-To see how `spawn_connected()` works, we will create a child task
+To see how `spawn_listener()` 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>) {
+fn stringifier(from_parent: comm::port<uint>,
+ to_parent: comm::chan<str>) {
let value: uint;
do {
- value = comm::recv(from_par);
- comm::send(to_par, uint::to_str(value, 10u));
+ value = comm::recv(from_parent);
+ comm::send(to_parent, 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 stringifier(from_par: comm::port<uint>,
-# to_par: comm::chan<str>) {
-# comm::send(to_par, "22");
-# comm::send(to_par, "23");
-# comm::send(to_par, "0");
+# fn stringifier(from_parent: comm::port<uint>,
+# to_parent: comm::chan<str>) {
+# comm::send(to_parent, "22");
+# comm::send(to_parent, "23");
+# comm::send(to_parent, "0");
# }
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.
-
-## Joining a task
-
-The function `spawn_joinable()` is used to spawn a task that can later
-be joined. This is implemented by having the child task send a message
-when it has completed (either successfully or by failing). Therefore,
-`spawn_joinable()` returns a structure containing both the task ID and
-the port where this message will be sent---this structure type is
-called `task::joinable_task`. The structure can be passed to
-`task::join()`, which simply blocks on the port, waiting to receive
-the message from the child task.
+ let from_child = comm::port();
+ let to_parent = comm::chan(from_child);
+ let to_child = task::spawn_listener {|from_parent|
+ stringifier(from_parent, to_parent);
+ };
+ comm::send(to_child, 22u);
+ assert comm::recv(from_child) == "22";
+ comm::send(to_child, 23u);
+ assert comm::recv(from_child) == "23";
+ comm::send(to_child, 0u);
+ assert comm::recv(from_child) == "0";
+}
+~~~~
+
+The parent first sets up a port to receive data from and a channel
+that the child can use to send data to that port. The call to
+`spawn_listener()` will spawn the child task, providing it with a port
+on which to receive data from its parent, and returning to the parent
+the associated channel. Finally, the closure passed to
+`spawn_listener()` that forms the body of the child task captures the
+`to_parent` channel in its environment, so both parent and child
+can send and receive data to and from the other.
## The supervisor relationship
@@ -143,8 +143,6 @@ fn monitor(f: fn~(diagnostic::emitter)) {
alt task::try {||
- task::unsupervise();
-
// The 'diagnostics emitter'. Every error, warning, etc. should
// go through this function.
let demitter = fn@(cmsp: option<(codemap::codemap, codemap::span)>,
@@ -54,11 +54,11 @@ fn run(lib_path: str, prog: str, args: [str],
writeclose(pipe_in.out, input);
let p = comm::port();
let ch = comm::chan(p);
- task::spawn_sched(1u) {||
+ task::spawn_sched(task::single_threaded) {||
let errput = readclose(pipe_err.in);
comm::send(ch, (2, errput));
};
- task::spawn_sched(1u) {||
+ task::spawn_sched(task::single_threaded) {||
let output = readclose(pipe_out.in);
comm::send(ch, (1, output));
};
View
@@ -35,8 +35,9 @@ enum rust_port {}
#[abi = "cdecl"]
native mod rustrt {
+ fn get_task_id() -> task_id;
fn chan_id_send<T: send>(t: *sys::type_desc,
- target_task: task::task, target_port: port_id,
+ target_task: task_id, target_port: port_id,
data: T) -> ctypes::uintptr_t;
fn new_port(unit_sz: ctypes::size_t) -> *rust_port;
@@ -58,6 +59,7 @@ native mod rusti {
fn call_with_retptr<T: send>(&&f: fn@(*uint)) -> T;
}
+type task_id = int;
type port_id = int;
// It's critical that this only have one variant, so it has a record
@@ -75,7 +77,7 @@ type port_id = int;
over other channels."
)]
enum chan<T: send> {
- chan_t(task::task, port_id)
+ chan_t(task_id, port_id)
}
resource port_ptr<T: send>(po: *rust_port) {
@@ -208,7 +210,7 @@ fn peek<T: send>(p: port<T>) -> bool {
port used to construct it."
)]
fn chan<T: send>(p: port<T>) -> chan<T> {
- chan_t(task::get_task(), rustrt::get_port_id(***p))
+ chan_t(rustrt::get_task_id(), rustrt::get_port_id(***p))
}
#[test]
Oops, something went wrong.

0 comments on commit 4220dcf

Please sign in to comment.