Better type inference for chans and ports.
This commit is contained in:
parent
f023f82090
commit
3ab21e5ee0
6 changed files with 65 additions and 59 deletions
|
@ -6,7 +6,7 @@ import task::task_id;
|
|||
|
||||
export _chan;
|
||||
export _port;
|
||||
|
||||
export chan_handle;
|
||||
export mk_port;
|
||||
export send;
|
||||
export recv;
|
||||
|
@ -32,10 +32,9 @@ native "rust-intrinsic" mod rusti {
|
|||
|
||||
type port_id = int;
|
||||
|
||||
type chan<~T> = {
|
||||
task : task_id,
|
||||
port : port_id
|
||||
};
|
||||
type chan_handle<~T> = { task : task_id, port : port_id};
|
||||
|
||||
tag chan<~T> { chan_t(chan_handle<T>); }
|
||||
type _chan<~T> = chan<T>;
|
||||
|
||||
resource port_ptr(po: *rustrt::rust_port) {
|
||||
|
@ -43,11 +42,11 @@ resource port_ptr(po: *rustrt::rust_port) {
|
|||
rustrt::del_port(po);
|
||||
}
|
||||
|
||||
type port<~T> = @port_ptr;
|
||||
tag port<~T> { port_t(@port_ptr); }
|
||||
|
||||
obj port_obj<~T>(raw_port : port<T>) {
|
||||
fn mk_chan() -> _chan<T> {
|
||||
chan::<T>(raw_port)
|
||||
fn mk_chan() -> chan<T> {
|
||||
chan(raw_port)
|
||||
}
|
||||
|
||||
fn recv() -> T {
|
||||
|
@ -60,21 +59,21 @@ fn mk_port<~T>() -> _port<T> {
|
|||
ret port_obj::<T>(port::<T>());
|
||||
}
|
||||
|
||||
fn send<~T>(ch : chan<T>, data : -T) {
|
||||
fn send<~T>(ch : &chan<T>, data : -T) {
|
||||
rustrt::chan_id_send(ch.task, ch.port, data);
|
||||
}
|
||||
|
||||
fn port<~T>() -> port<T> {
|
||||
@port_ptr(rustrt::new_port(sys::size_of::<T>()))
|
||||
port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>())))
|
||||
}
|
||||
|
||||
fn recv<~T>(p : port<T>) -> T {
|
||||
ret rusti::recv(**p)
|
||||
fn recv<~T>(p : &port<T>) -> T {
|
||||
ret rusti::recv(***p)
|
||||
}
|
||||
|
||||
fn chan<~T>(p : port<T>) -> chan<T> {
|
||||
{
|
||||
fn chan<~T>(p : &port<T>) -> chan<T> {
|
||||
chan_t({
|
||||
task: task::get_task_id(),
|
||||
port: rustrt::get_port_id(**p)
|
||||
}
|
||||
port: rustrt::get_port_id(***p)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import cast = unsafe::reinterpret_cast;
|
||||
import comm;
|
||||
import comm::_chan;
|
||||
import option::some;
|
||||
import option::none;
|
||||
import option = option::t;
|
||||
|
@ -33,7 +32,7 @@ native "rust" mod rustrt {
|
|||
type rust_task = {
|
||||
id : task,
|
||||
mutable notify_enabled : u8,
|
||||
mutable notify_chan : _chan<task_notification>,
|
||||
mutable notify_chan : comm::chan_handle<task_notification>,
|
||||
ctx : task_context,
|
||||
stack_ptr : *u8
|
||||
};
|
||||
|
@ -76,14 +75,12 @@ tag task_notification {
|
|||
fn join(task_port : (task_id, comm::port<task_notification>))
|
||||
-> task_result {
|
||||
let (id, port) = task_port;
|
||||
while true {
|
||||
alt comm::recv::<task_notification>(port) {
|
||||
exit(_id, res) {
|
||||
if _id == id { ret res }
|
||||
}
|
||||
}
|
||||
alt comm::recv::<task_notification>(port) {
|
||||
exit(_id, res) {
|
||||
if _id == id { ret res }
|
||||
else { fail #fmt("join received id %d, expected %d", _id, id) }
|
||||
}
|
||||
}
|
||||
fail
|
||||
}
|
||||
|
||||
fn join_id(t : task_id) -> task_result {
|
||||
|
@ -108,7 +105,7 @@ fn spawn(thunk : -fn() -> ()) -> task {
|
|||
spawn_inner(thunk, none)
|
||||
}
|
||||
|
||||
fn spawn_notify(thunk : -fn() -> (), notify : _chan<task_notification>)
|
||||
fn spawn_notify(thunk : -fn() -> (), notify : comm::chan<task_notification>)
|
||||
-> task {
|
||||
spawn_inner(thunk, some(notify))
|
||||
}
|
||||
|
@ -121,7 +118,7 @@ fn spawn_joinable(thunk : -fn()) -> (task_id, comm::port<task_notification>) {
|
|||
|
||||
// FIXME: make this a fn~ once those are supported.
|
||||
fn spawn_inner(thunk : -fn() -> (),
|
||||
notify : option<_chan<task_notification>>)
|
||||
notify : option<comm::chan<task_notification>>)
|
||||
-> task_id {
|
||||
let id = rustrt::new_task();
|
||||
|
||||
|
@ -144,7 +141,7 @@ fn spawn_inner(thunk : -fn() -> (),
|
|||
alt notify {
|
||||
some(c) {
|
||||
(**task_ptr).notify_enabled = 1u8;
|
||||
(**task_ptr).notify_chan = c;
|
||||
(**task_ptr).notify_chan = *c;
|
||||
}
|
||||
none {}
|
||||
};
|
||||
|
|
|
@ -14,10 +14,10 @@ import std::os;
|
|||
import std::run;
|
||||
import std::io;
|
||||
import std::str;
|
||||
import std::comm::_chan;
|
||||
import std::comm::mk_port;
|
||||
import std::comm::_port;
|
||||
import std::comm::chan;
|
||||
import std::comm::port;
|
||||
import std::comm::send;
|
||||
import std::comm::recv;
|
||||
|
||||
export handle;
|
||||
export mk;
|
||||
|
@ -26,27 +26,27 @@ export run;
|
|||
export close;
|
||||
export reqchan;
|
||||
|
||||
type reqchan = _chan<request>;
|
||||
type reqchan = chan<request>;
|
||||
|
||||
type handle = {task: option::t<task_id>, chan: reqchan};
|
||||
|
||||
tag request {
|
||||
exec([u8], [u8], [[u8]], _chan<response>);
|
||||
exec([u8], [u8], [[u8]], chan<response>);
|
||||
stop;
|
||||
}
|
||||
|
||||
type response = {pid: int, infd: int, outfd: int, errfd: int};
|
||||
|
||||
fn mk() -> handle {
|
||||
let setupport = mk_port();
|
||||
let task = task::_spawn(bind fn(setupchan: _chan<_chan<request>>) {
|
||||
let reqport = mk_port();
|
||||
let reqchan = reqport.mk_chan();
|
||||
let setupport = port();
|
||||
let task = task::spawn(bind fn(setupchan: chan<chan<request>>) {
|
||||
let reqport = port();
|
||||
let reqchan = chan(reqport);
|
||||
send(setupchan, reqchan);
|
||||
worker(reqport);
|
||||
} (setupport.mk_chan()));
|
||||
} (chan(setupport)));
|
||||
ret {task: option::some(task),
|
||||
chan: setupport.recv()
|
||||
chan: recv(setupport)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -60,13 +60,13 @@ fn close(handle: &handle) {
|
|||
fn run(handle: &handle, lib_path: &str,
|
||||
prog: &str, args: &[str], input: &option::t<str>) ->
|
||||
{status: int, out: str, err: str} {
|
||||
let p = mk_port::<response>();
|
||||
let ch = p.mk_chan();
|
||||
let p = port();
|
||||
let ch = chan(p);
|
||||
send(handle.chan, exec(str::bytes(lib_path),
|
||||
str::bytes(prog),
|
||||
clone_ivecstr(args),
|
||||
ch));
|
||||
let resp = p.recv();
|
||||
let resp = recv(p);
|
||||
|
||||
writeclose(resp.infd, input);
|
||||
let output = readclose(resp.outfd);
|
||||
|
@ -99,18 +99,12 @@ fn readclose(fd: int) -> str {
|
|||
ret buf;
|
||||
}
|
||||
|
||||
fn worker(p: _port<request>) {
|
||||
fn worker(p: port<request>) {
|
||||
|
||||
// FIXME (787): If we declare this inside of the while loop and then
|
||||
// break out of it before it's ever initialized (i.e. we don't run
|
||||
// any tests), then the cleanups will puke, so we're initializing it
|
||||
// here with defaults.
|
||||
let execparms = {
|
||||
lib_path: "",
|
||||
prog: "",
|
||||
args: ~[],
|
||||
respchan: p.mk_chan()
|
||||
};
|
||||
// any tests), then the cleanups will puke.
|
||||
let execparms;
|
||||
|
||||
while true {
|
||||
// FIXME: Sending strings across channels seems to still
|
||||
|
@ -124,7 +118,7 @@ fn worker(p: _port<request>) {
|
|||
// put the entire alt in another block to make sure the exec
|
||||
// message goes out of scope. Seems like the scoping rules for
|
||||
// the alt discriminant are wrong.
|
||||
alt p.recv() {
|
||||
alt recv(p) {
|
||||
exec(lib_path, prog, args, respchan) {
|
||||
{
|
||||
lib_path: str::unsafe_from_bytes(lib_path),
|
||||
|
|
|
@ -4,7 +4,7 @@ import std::comm::_chan;
|
|||
import std::comm::mk_port;
|
||||
import std::comm::send;
|
||||
|
||||
fn echo<~T>(c: _chan<T>, oc: _chan<_chan<T>>) {
|
||||
fn echo<~T>(c: &_chan<T>, oc: &_chan<_chan<T>>) {
|
||||
// Tests that the type argument in port gets
|
||||
// visited
|
||||
let p = mk_port::<T>();
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use std;
|
||||
import std::comm::_chan;
|
||||
import std::comm::chan;
|
||||
import std::comm::send;
|
||||
import std::comm::mk_port;
|
||||
import std::comm::port;
|
||||
|
||||
// tests that ctrl's type gets inferred properly
|
||||
type command<K, V> = {key: K, val: V};
|
||||
type command<~K, ~V> = {key: K, val: V};
|
||||
|
||||
fn cache_server<K, V>(c: _chan<_chan<command<K, V>>>) {
|
||||
let ctrl = mk_port::<_chan<command<K, V>>>();
|
||||
send(c, ctrl.mk_chan());
|
||||
fn cache_server<~K, ~V>(c: &chan<chan<command<K, V>>>) {
|
||||
let ctrl = port();
|
||||
send(c, chan(ctrl));
|
||||
}
|
||||
fn main() { }
|
||||
|
|
|
@ -25,3 +25,19 @@ fn send_recv_fn() {
|
|||
comm::send(c, 42);
|
||||
assert(comm::recv(p) == 42);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn send_recv_fn_infer() {
|
||||
let p = comm::port();
|
||||
let c = comm::chan(p);
|
||||
comm::send(c, 42);
|
||||
assert(comm::recv(p) == 42);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn chan_chan() {
|
||||
let p = comm::port(), p2 = comm::port::<int>();
|
||||
let c = comm::chan(p);
|
||||
comm::send(c, comm::chan(p2));
|
||||
let c2 = comm::recv(p);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue