Skip to content

Commit abf4421

Browse files
committed
Generate try_send versions for all the messages. Fixes #3128
1 parent 672bfa5 commit abf4421

File tree

3 files changed

+122
-78
lines changed

3 files changed

+122
-78
lines changed

src/libcore/pipes.rs

+24-21
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ struct buffer_resource<T: send> {
337337

338338
#[doc(hidden)]
339339
fn send<T: send, Tbuffer: send>(-p: send_packet_buffered<T, Tbuffer>,
340-
-payload: T) {
340+
-payload: T) -> bool {
341341
let header = p.header();
342342
let p_ = p.unwrap();
343343
let p = unsafe { &*p_ };
@@ -346,29 +346,32 @@ fn send<T: send, Tbuffer: send>(-p: send_packet_buffered<T, Tbuffer>,
346346
p.payload <- some(payload);
347347
let old_state = swap_state_rel(p.header.state, full);
348348
match old_state {
349-
empty => {
350-
// Yay, fastpath.
349+
empty => {
350+
// Yay, fastpath.
351351

352-
// The receiver will eventually clean this up.
353-
//unsafe { forget(p); }
354-
}
355-
full => fail ~"duplicate send",
356-
blocked => {
357-
debug!{"waking up task for %?", p_};
358-
let old_task = swap_task(p.header.blocked_task, ptr::null());
359-
if !old_task.is_null() {
360-
rustrt::task_signal_event(
361-
old_task, ptr::addr_of(p.header) as *libc::c_void);
362-
rustrt::rust_task_deref(old_task);
352+
// The receiver will eventually clean this up.
353+
//unsafe { forget(p); }
354+
return true;
363355
}
356+
full => fail ~"duplicate send",
357+
blocked => {
358+
debug!{"waking up task for %?", p_};
359+
let old_task = swap_task(p.header.blocked_task, ptr::null());
360+
if !old_task.is_null() {
361+
rustrt::task_signal_event(
362+
old_task, ptr::addr_of(p.header) as *libc::c_void);
363+
rustrt::rust_task_deref(old_task);
364+
}
364365

365-
// The receiver will eventually clean this up.
366-
//unsafe { forget(p); }
367-
}
368-
terminated => {
369-
// The receiver will never receive this. Rely on drop_glue
370-
// to clean everything up.
371-
}
366+
// The receiver will eventually clean this up.
367+
//unsafe { forget(p); }
368+
return true;
369+
}
370+
terminated => {
371+
// The receiver will never receive this. Rely on drop_glue
372+
// to clean everything up.
373+
return false;
374+
}
372375
}
373376
}
374377

src/libsyntax/ext/pipes/ast_builder.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ mod syntax {
1515
export parse;
1616
}
1717

18-
fn ident(s: ~str) -> ast::ident {
19-
@(copy s)
18+
fn ident(s: &str) -> ast::ident {
19+
@(s.to_unique())
2020
}
2121

2222
fn path(id: ident, span: span) -> @ast::path {
@@ -86,9 +86,15 @@ trait ext_ctxt_ast_builder {
8686
fn stmt_expr(e: @ast::expr) -> @ast::stmt;
8787
fn block_expr(b: ast::blk) -> @ast::expr;
8888
fn empty_span() -> span;
89+
fn ty_option(ty: @ast::ty) -> @ast::ty;
8990
}
9091

9192
impl ast_builder of ext_ctxt_ast_builder for ext_ctxt {
93+
fn ty_option(ty: @ast::ty) -> @ast::ty {
94+
self.ty_path_ast_builder(path(@~"option", self.empty_span())
95+
.add_ty(ty))
96+
}
97+
9298
fn empty_span() -> span {
9399
{lo: 0, hi: 0, expn_info: self.backtrace()}
94100
}

src/libsyntax/ext/pipes/pipec.rs

+90-55
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ mod syntax {
3131
}
3232

3333
trait gen_send {
34-
fn gen_send(cx: ext_ctxt) -> @ast::item;
34+
fn gen_send(cx: ext_ctxt, try: bool) -> @ast::item;
3535
}
3636

3737
trait to_type_decls {
@@ -45,12 +45,12 @@ trait gen_init {
4545
}
4646

4747
impl compile of gen_send for message {
48-
fn gen_send(cx: ext_ctxt) -> @ast::item {
48+
fn gen_send(cx: ext_ctxt, try: bool) -> @ast::item {
4949
debug!{"pipec: gen_send"};
5050
match self {
5151
message(id, span, tys, this,
5252
some({state: next, tys: next_tys})) => {
53-
debug!{"pipec: next state exists"};
53+
debug!("pipec: next state exists");
5454
let next = this.proto.get_state(next);
5555
assert next_tys.len() == next.ty_params.len();
5656
let arg_names = tys.mapi(|i, _ty| @(~"x_" + i.to_str()));
@@ -79,85 +79,119 @@ impl compile of gen_send for message {
7979
};
8080

8181
body += ~"let b = pipe.reuse_buffer();\n";
82-
body += fmt!{"let %s = pipes::send_packet_buffered(\
82+
body += fmt!("let %s = pipes::send_packet_buffered(\
8383
ptr::addr_of(b.buffer.data.%s));\n",
84-
sp, *next.name};
85-
body += fmt!{"let %s = pipes::recv_packet_buffered(\
84+
sp, *next.name);
85+
body += fmt!("let %s = pipes::recv_packet_buffered(\
8686
ptr::addr_of(b.buffer.data.%s));\n",
87-
rp, *next.name};
87+
rp, *next.name);
8888
}
8989
else {
9090
let pat = match (this.dir, next.dir) {
91-
(send, send) => ~"(c, s)",
92-
(send, recv) => ~"(s, c)",
93-
(recv, send) => ~"(s, c)",
94-
(recv, recv) => ~"(c, s)"
91+
(send, send) => "(c, s)",
92+
(send, recv) => "(s, c)",
93+
(recv, send) => "(s, c)",
94+
(recv, recv) => "(c, s)"
9595
};
9696

97-
body += fmt!{"let %s = pipes::entangle();\n", pat};
97+
body += fmt!("let %s = pipes::entangle();\n", pat);
9898
}
99-
body += fmt!{"let message = %s::%s(%s);\n",
99+
body += fmt!("let message = %s::%s(%s);\n",
100100
*this.proto.name,
101101
*self.name(),
102102
str::connect(vec::append_one(arg_names, @~"s")
103103
.map(|x| *x),
104-
~", ")};
105-
body += fmt!{"pipes::send(pipe, message);\n"};
106-
// return the new channel
107-
body += ~"c }";
104+
~", "));
105+
106+
if !try {
107+
body += fmt!{"pipes::send(pipe, message);\n"};
108+
// return the new channel
109+
body += ~"c }";
110+
}
111+
else {
112+
body += fmt!("if pipes::send(pipe, message) {\n \
113+
some(c) \
114+
} else { none } }");
115+
}
108116

109117
let body = cx.parse_expr(body);
110118

111-
cx.item_fn_poly(self.name(),
119+
let mut rty = cx.ty_path_ast_builder(path(next.data_name(),
120+
span)
121+
.add_tys(next_tys));
122+
if try {
123+
rty = cx.ty_option(rty);
124+
}
125+
126+
let name = if try {
127+
@(~"try_" + *self.name())
128+
}
129+
else { self.name() };
130+
131+
cx.item_fn_poly(name,
112132
args_ast,
113-
cx.ty_path_ast_builder(path(next.data_name(),
114-
span)
115-
.add_tys(next_tys)),
133+
rty,
116134
self.get_params(),
117135
cx.expr_block(body))
118136
}
119137
120-
message(id, span, tys, this, none) => {
121-
debug!{"pipec: no next state"};
122-
let arg_names = tys.mapi(|i, _ty| @(~"x_" + i.to_str()));
138+
message(id, span, tys, this, none) => {
139+
debug!{"pipec: no next state"};
140+
let arg_names = tys.mapi(|i, _ty| @(~"x_" + i.to_str()));
123141
124-
let args_ast = (arg_names, tys).map(
125-
|n, t| cx.arg_mode(n, t, ast::by_copy)
126-
);
142+
let args_ast = (arg_names, tys).map(
143+
|n, t| cx.arg_mode(n, t, ast::by_copy)
144+
);
127145
128-
let args_ast = vec::append(
129-
~[cx.arg_mode(@~"pipe",
130-
cx.ty_path_ast_builder(path(this.data_name(),
131-
span)
132-
.add_tys(cx.ty_vars(this.ty_params))),
133-
ast::by_copy)],
134-
args_ast);
146+
let args_ast = vec::append(
147+
~[cx.arg_mode(@~"pipe",
148+
cx.ty_path_ast_builder(
149+
path(this.data_name(), span)
150+
.add_tys(cx.ty_vars(this.ty_params))),
151+
ast::by_copy)],
152+
args_ast);
135153
136-
let message_args = if arg_names.len() == 0 {
137-
~""
138-
}
139-
else {
140-
~"(" + str::connect(arg_names.map(|x| *x), ~", ") + ~")"
141-
};
154+
let message_args = if arg_names.len() == 0 {
155+
~""
156+
}
157+
else {
158+
~"(" + str::connect(arg_names.map(|x| *x), ~", ") + ~")"
159+
};
142160
143-
let mut body = ~"{ ";
144-
body += fmt!{"let message = %s::%s%s;\n",
145-
*this.proto.name,
146-
*self.name(),
147-
message_args};
148-
body += fmt!{"pipes::send(pipe, message);\n"};
149-
body += ~" }";
161+
let mut body = ~"{ ";
162+
body += fmt!{"let message = %s::%s%s;\n",
163+
*this.proto.name,
164+
*self.name(),
165+
message_args};
166+
167+
if !try {
168+
body += fmt!{"pipes::send(pipe, message);\n"};
169+
body += ~" }";
170+
} else {
171+
body += fmt!("if pipes::send(pipe, message) { \
172+
some(()) \
173+
} else { none } }");
174+
}
150175
151-
let body = cx.parse_expr(body);
176+
let body = cx.parse_expr(body);
152177
153-
cx.item_fn_poly(self.name(),
154-
args_ast,
155-
cx.ty_nil_ast_builder(),
156-
self.get_params(),
157-
cx.expr_block(body))
178+
let name = if try {
179+
@(~"try_" + *self.name())
180+
}
181+
else { self.name() };
182+
183+
cx.item_fn_poly(name,
184+
args_ast,
185+
if try {
186+
cx.ty_option(cx.ty_nil_ast_builder())
187+
} else {
188+
cx.ty_nil_ast_builder()
189+
},
190+
self.get_params(),
191+
cx.expr_block(body))
192+
}
158193
}
159194
}
160-
}
161195
162196
fn to_ty(cx: ext_ctxt) -> @ast::ty {
163197
cx.ty_path_ast_builder(path(self.name(), self.span())
@@ -215,7 +249,8 @@ impl compile of to_type_decls for state {
215249
let mut items = ~[];
216250
for self.messages.each |m| {
217251
if dir == send {
218-
vec::push(items, m.gen_send(cx))
252+
vec::push(items, m.gen_send(cx, true));
253+
vec::push(items, m.gen_send(cx, false));
219254
}
220255
}
221256

0 commit comments

Comments
 (0)