Generate try_send versions for all the messages. Fixes #3128
This commit is contained in:
parent
672bfa5773
commit
abf4421e7c
@ -337,7 +337,7 @@ struct buffer_resource<T: send> {
|
||||
|
||||
#[doc(hidden)]
|
||||
fn send<T: send, Tbuffer: send>(-p: send_packet_buffered<T, Tbuffer>,
|
||||
-payload: T) {
|
||||
-payload: T) -> bool {
|
||||
let header = p.header();
|
||||
let p_ = p.unwrap();
|
||||
let p = unsafe { &*p_ };
|
||||
@ -346,29 +346,32 @@ fn send<T: send, Tbuffer: send>(-p: send_packet_buffered<T, Tbuffer>,
|
||||
p.payload <- some(payload);
|
||||
let old_state = swap_state_rel(p.header.state, full);
|
||||
match old_state {
|
||||
empty => {
|
||||
// Yay, fastpath.
|
||||
empty => {
|
||||
// Yay, fastpath.
|
||||
|
||||
// The receiver will eventually clean this up.
|
||||
//unsafe { forget(p); }
|
||||
}
|
||||
full => fail ~"duplicate send",
|
||||
blocked => {
|
||||
debug!{"waking up task for %?", p_};
|
||||
let old_task = swap_task(p.header.blocked_task, ptr::null());
|
||||
if !old_task.is_null() {
|
||||
rustrt::task_signal_event(
|
||||
old_task, ptr::addr_of(p.header) as *libc::c_void);
|
||||
rustrt::rust_task_deref(old_task);
|
||||
// The receiver will eventually clean this up.
|
||||
//unsafe { forget(p); }
|
||||
return true;
|
||||
}
|
||||
full => fail ~"duplicate send",
|
||||
blocked => {
|
||||
debug!{"waking up task for %?", p_};
|
||||
let old_task = swap_task(p.header.blocked_task, ptr::null());
|
||||
if !old_task.is_null() {
|
||||
rustrt::task_signal_event(
|
||||
old_task, ptr::addr_of(p.header) as *libc::c_void);
|
||||
rustrt::rust_task_deref(old_task);
|
||||
}
|
||||
|
||||
// The receiver will eventually clean this up.
|
||||
//unsafe { forget(p); }
|
||||
}
|
||||
terminated => {
|
||||
// The receiver will never receive this. Rely on drop_glue
|
||||
// to clean everything up.
|
||||
}
|
||||
// The receiver will eventually clean this up.
|
||||
//unsafe { forget(p); }
|
||||
return true;
|
||||
}
|
||||
terminated => {
|
||||
// The receiver will never receive this. Rely on drop_glue
|
||||
// to clean everything up.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,8 +15,8 @@ mod syntax {
|
||||
export parse;
|
||||
}
|
||||
|
||||
fn ident(s: ~str) -> ast::ident {
|
||||
@(copy s)
|
||||
fn ident(s: &str) -> ast::ident {
|
||||
@(s.to_unique())
|
||||
}
|
||||
|
||||
fn path(id: ident, span: span) -> @ast::path {
|
||||
@ -86,9 +86,15 @@ trait ext_ctxt_ast_builder {
|
||||
fn stmt_expr(e: @ast::expr) -> @ast::stmt;
|
||||
fn block_expr(b: ast::blk) -> @ast::expr;
|
||||
fn empty_span() -> span;
|
||||
fn ty_option(ty: @ast::ty) -> @ast::ty;
|
||||
}
|
||||
|
||||
impl ast_builder of ext_ctxt_ast_builder for ext_ctxt {
|
||||
fn ty_option(ty: @ast::ty) -> @ast::ty {
|
||||
self.ty_path_ast_builder(path(@~"option", self.empty_span())
|
||||
.add_ty(ty))
|
||||
}
|
||||
|
||||
fn empty_span() -> span {
|
||||
{lo: 0, hi: 0, expn_info: self.backtrace()}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ mod syntax {
|
||||
}
|
||||
|
||||
trait gen_send {
|
||||
fn gen_send(cx: ext_ctxt) -> @ast::item;
|
||||
fn gen_send(cx: ext_ctxt, try: bool) -> @ast::item;
|
||||
}
|
||||
|
||||
trait to_type_decls {
|
||||
@ -45,12 +45,12 @@ trait gen_init {
|
||||
}
|
||||
|
||||
impl compile of gen_send for message {
|
||||
fn gen_send(cx: ext_ctxt) -> @ast::item {
|
||||
fn gen_send(cx: ext_ctxt, try: bool) -> @ast::item {
|
||||
debug!{"pipec: gen_send"};
|
||||
match self {
|
||||
message(id, span, tys, this,
|
||||
some({state: next, tys: next_tys})) => {
|
||||
debug!{"pipec: next state exists"};
|
||||
debug!("pipec: next state exists");
|
||||
let next = this.proto.get_state(next);
|
||||
assert next_tys.len() == next.ty_params.len();
|
||||
let arg_names = tys.mapi(|i, _ty| @(~"x_" + i.to_str()));
|
||||
@ -79,85 +79,119 @@ impl compile of gen_send for message {
|
||||
};
|
||||
|
||||
body += ~"let b = pipe.reuse_buffer();\n";
|
||||
body += fmt!{"let %s = pipes::send_packet_buffered(\
|
||||
body += fmt!("let %s = pipes::send_packet_buffered(\
|
||||
ptr::addr_of(b.buffer.data.%s));\n",
|
||||
sp, *next.name};
|
||||
body += fmt!{"let %s = pipes::recv_packet_buffered(\
|
||||
sp, *next.name);
|
||||
body += fmt!("let %s = pipes::recv_packet_buffered(\
|
||||
ptr::addr_of(b.buffer.data.%s));\n",
|
||||
rp, *next.name};
|
||||
rp, *next.name);
|
||||
}
|
||||
else {
|
||||
let pat = match (this.dir, next.dir) {
|
||||
(send, send) => ~"(c, s)",
|
||||
(send, recv) => ~"(s, c)",
|
||||
(recv, send) => ~"(s, c)",
|
||||
(recv, recv) => ~"(c, s)"
|
||||
(send, send) => "(c, s)",
|
||||
(send, recv) => "(s, c)",
|
||||
(recv, send) => "(s, c)",
|
||||
(recv, recv) => "(c, s)"
|
||||
};
|
||||
|
||||
body += fmt!{"let %s = pipes::entangle();\n", pat};
|
||||
body += fmt!("let %s = pipes::entangle();\n", pat);
|
||||
}
|
||||
body += fmt!{"let message = %s::%s(%s);\n",
|
||||
body += fmt!("let message = %s::%s(%s);\n",
|
||||
*this.proto.name,
|
||||
*self.name(),
|
||||
str::connect(vec::append_one(arg_names, @~"s")
|
||||
.map(|x| *x),
|
||||
~", ")};
|
||||
body += fmt!{"pipes::send(pipe, message);\n"};
|
||||
// return the new channel
|
||||
body += ~"c }";
|
||||
~", "));
|
||||
|
||||
let body = cx.parse_expr(body);
|
||||
|
||||
cx.item_fn_poly(self.name(),
|
||||
args_ast,
|
||||
cx.ty_path_ast_builder(path(next.data_name(),
|
||||
span)
|
||||
.add_tys(next_tys)),
|
||||
self.get_params(),
|
||||
cx.expr_block(body))
|
||||
}
|
||||
|
||||
message(id, span, tys, this, none) => {
|
||||
debug!{"pipec: no next state"};
|
||||
let arg_names = tys.mapi(|i, _ty| @(~"x_" + i.to_str()));
|
||||
|
||||
let args_ast = (arg_names, tys).map(
|
||||
|n, t| cx.arg_mode(n, t, ast::by_copy)
|
||||
);
|
||||
|
||||
let args_ast = vec::append(
|
||||
~[cx.arg_mode(@~"pipe",
|
||||
cx.ty_path_ast_builder(path(this.data_name(),
|
||||
span)
|
||||
.add_tys(cx.ty_vars(this.ty_params))),
|
||||
ast::by_copy)],
|
||||
args_ast);
|
||||
|
||||
let message_args = if arg_names.len() == 0 {
|
||||
~""
|
||||
if !try {
|
||||
body += fmt!{"pipes::send(pipe, message);\n"};
|
||||
// return the new channel
|
||||
body += ~"c }";
|
||||
}
|
||||
else {
|
||||
~"(" + str::connect(arg_names.map(|x| *x), ~", ") + ~")"
|
||||
};
|
||||
|
||||
let mut body = ~"{ ";
|
||||
body += fmt!{"let message = %s::%s%s;\n",
|
||||
*this.proto.name,
|
||||
*self.name(),
|
||||
message_args};
|
||||
body += fmt!{"pipes::send(pipe, message);\n"};
|
||||
body += ~" }";
|
||||
body += fmt!("if pipes::send(pipe, message) {\n \
|
||||
some(c) \
|
||||
} else { none } }");
|
||||
}
|
||||
|
||||
let body = cx.parse_expr(body);
|
||||
|
||||
cx.item_fn_poly(self.name(),
|
||||
let mut rty = cx.ty_path_ast_builder(path(next.data_name(),
|
||||
span)
|
||||
.add_tys(next_tys));
|
||||
if try {
|
||||
rty = cx.ty_option(rty);
|
||||
}
|
||||
|
||||
let name = if try {
|
||||
@(~"try_" + *self.name())
|
||||
}
|
||||
else { self.name() };
|
||||
|
||||
cx.item_fn_poly(name,
|
||||
args_ast,
|
||||
cx.ty_nil_ast_builder(),
|
||||
rty,
|
||||
self.get_params(),
|
||||
cx.expr_block(body))
|
||||
}
|
||||
|
||||
message(id, span, tys, this, none) => {
|
||||
debug!{"pipec: no next state"};
|
||||
let arg_names = tys.mapi(|i, _ty| @(~"x_" + i.to_str()));
|
||||
|
||||
let args_ast = (arg_names, tys).map(
|
||||
|n, t| cx.arg_mode(n, t, ast::by_copy)
|
||||
);
|
||||
|
||||
let args_ast = vec::append(
|
||||
~[cx.arg_mode(@~"pipe",
|
||||
cx.ty_path_ast_builder(
|
||||
path(this.data_name(), span)
|
||||
.add_tys(cx.ty_vars(this.ty_params))),
|
||||
ast::by_copy)],
|
||||
args_ast);
|
||||
|
||||
let message_args = if arg_names.len() == 0 {
|
||||
~""
|
||||
}
|
||||
else {
|
||||
~"(" + str::connect(arg_names.map(|x| *x), ~", ") + ~")"
|
||||
};
|
||||
|
||||
let mut body = ~"{ ";
|
||||
body += fmt!{"let message = %s::%s%s;\n",
|
||||
*this.proto.name,
|
||||
*self.name(),
|
||||
message_args};
|
||||
|
||||
if !try {
|
||||
body += fmt!{"pipes::send(pipe, message);\n"};
|
||||
body += ~" }";
|
||||
} else {
|
||||
body += fmt!("if pipes::send(pipe, message) { \
|
||||
some(()) \
|
||||
} else { none } }");
|
||||
}
|
||||
|
||||
let body = cx.parse_expr(body);
|
||||
|
||||
let name = if try {
|
||||
@(~"try_" + *self.name())
|
||||
}
|
||||
else { self.name() };
|
||||
|
||||
cx.item_fn_poly(name,
|
||||
args_ast,
|
||||
if try {
|
||||
cx.ty_option(cx.ty_nil_ast_builder())
|
||||
} else {
|
||||
cx.ty_nil_ast_builder()
|
||||
},
|
||||
self.get_params(),
|
||||
cx.expr_block(body))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn to_ty(cx: ext_ctxt) -> @ast::ty {
|
||||
cx.ty_path_ast_builder(path(self.name(), self.span())
|
||||
@ -215,7 +249,8 @@ impl compile of to_type_decls for state {
|
||||
let mut items = ~[];
|
||||
for self.messages.each |m| {
|
||||
if dir == send {
|
||||
vec::push(items, m.gen_send(cx))
|
||||
vec::push(items, m.gen_send(cx, true));
|
||||
vec::push(items, m.gen_send(cx, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user