-
Notifications
You must be signed in to change notification settings - Fork 14k
Description
The primitives provided in task and comm are very primitive. Too primitive to write a tutorial chapter about without sounding completely lame. So I tried to write a helper function which helps create a channel back from a child task to its parent. None of the existing tests or examples seem to do this. And, apparently, with good reason.
Below is what I have. It doesn't work. Writing new task-creation utilities will typically require type parameters. We currently can not spawn functions with type parameters, so the 'landing pad' helper that such a utility would spawn can not be generic.
I half got around this with a clunky reinterpret_cast, but the resulting program doesn't work when the To type has a different size than an int, because the port being created in helper doesn't know its type.
Not being able to write generic utility functions around task spawning seems unacceptable. I'm marking this as a blocker because I don't think we can release a language that is supposed to have tasks as one of its interesting features with such a primitive set of task operations. I'm holding off on writing the tutorial section about tasks until we figure out a solution here. (Or maybe it already exists and I just didn't see it.)
use std;
import std::{task, comm};
type connected_fn<To, From> = fn(comm::port<To>, comm::chan<From>);
fn spawn_connected<uniq To, uniq From>(f: connected_fn<To, From>)
-> {task: task::task, in: comm::port<From>, out: comm::chan<To>} unsafe {
fn helper(d: (comm::chan<int>,
comm::chan<comm::chan<int>>,
connected_fn<int, int>)) {
let (out, send_in, f) = d;
let in = comm::port::<int>();
comm::send(send_in, comm::chan(in));
f(in, out);
}
let in = comm::port::<From>();
let get_out = comm::port::<comm::chan<To>>();
let task = task::spawn((comm::chan(in), comm::chan(get_out), f),
std::unsafe::reinterpret_cast(helper));
ret {task: task, in: in, out: comm::recv(get_out)};
}
tag msg { msg(int); quit; }
fn worker(in: comm::port<msg>, out: comm::chan<int>) {
while true {
alt comm::recv(in) {
msg(i) { comm::send(out, i * 10); }
quit. { break; }
}
}
}
fn main() {
let {task, in, out} = spawn_connected(worker);
comm::send(out, msg(20));
log_err comm::recv(in);
comm::send(out, quit);
}