Skip to content

Task system is embarrassingly unexpressive #1128

Closed
@marijnh

Description

@marijnh

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);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions