Refactor the bounded pingpong example to avoid needing to generate unsafe code.

Took some steps towards bounded codegen.
This commit is contained in:
Eric Holk 2012-07-23 13:50:12 -07:00
parent 88877effa8
commit c28af26258
4 changed files with 55 additions and 26 deletions

View file

@ -8,7 +8,7 @@ import arc::methods;
// Things used by code generated by the pipe compiler.
export entangle, get_buffer, drop_buffer;
export send_packet_buffered, recv_packet_buffered;
export mk_packet;
export mk_packet, entangle_buffer, has_buffer;
// export these so we can find them in the buffer_resource
// destructor. This is probably another metadata bug.
@ -151,6 +151,16 @@ type packet<T: send> = {
mut payload: option<T>,
};
trait has_buffer {
fn set_buffer(b: *libc::c_void);
}
impl methods<T: send> of has_buffer for packet<T> {
fn set_buffer(b: *libc::c_void) {
self.header.buffer = b;
}
}
fn mk_packet<T: send>() -> packet<T> {
{
header: packet_header(),
@ -182,6 +192,16 @@ fn packet<T: send>() -> *packet<T> {
p
}
fn entangle_buffer<T: send, Tstart: send>(
-buffer: ~buffer<T>,
init: fn(*libc::c_void, x: &T) -> *packet<Tstart>)
-> (send_packet_buffered<Tstart, T>, recv_packet_buffered<Tstart, T>)
{
let p = init(unsafe { reinterpret_cast(buffer) }, &buffer.data);
unsafe { forget(buffer) }
(send_packet_buffered(p), recv_packet_buffered(p))
}
#[abi = "rust-intrinsic"]
extern mod rusti {
fn atomic_xchng(&dst: int, src: int) -> int;

View file

@ -84,8 +84,11 @@ fn analyze(proto: protocol, _cx: ext_ctxt) {
// involving these states: %s",
// *proto.name,
// states));
proto.bounded = some(false);
}
else {
#debug("protocol %s is bounded. yay!", *proto.name);
proto.bounded = some(true);
}
}

View file

@ -98,23 +98,23 @@ impl methods for state {
}
}
enum protocol {
protocol_(@{
name: ident,
states: dvec<state>,
}),
type protocol = @protocol_;
fn protocol(name: ident) -> protocol { @protocol_(name) }
class protocol_ {
let name: ident;
let states: dvec<state>;
let mut bounded: option<bool>;
new(name: ident) {
self.name = name;
self.states = dvec();
self.bounded = none;
}
fn protocol(name: ident) -> protocol {
protocol_(@{name: name, states: dvec()})
}
impl methods for protocol {
fn add_state(name: ident, dir: direction) -> state {
self.add_state_poly(name, dir, ~[])
}
/// Get or create a state.
/// Get a state.
fn get_state(name: ident) -> state {
self.states.find(|i| i.name == name).get()
}
@ -125,6 +125,20 @@ impl methods for protocol {
self.states.find(|i| i.name == name) != none
}
fn filename() -> ~str {
~"proto://" + *self.name
}
fn num_states() -> uint { self.states.len() }
fn is_bounded() -> bool { self.bounded.get() }
}
impl methods for protocol {
fn add_state(name: ident, dir: direction) -> state {
self.add_state_poly(name, dir, ~[])
}
fn add_state_poly(name: ident, dir: direction,
+ty_params: ~[ast::ty_param]) -> state {
let messages = dvec();
@ -141,12 +155,6 @@ impl methods for protocol {
self.states.push(state);
state
}
fn filename() -> ~str {
~"proto://" + *self.name
}
fn num_states() -> uint { self.states.len() }
}
trait visitor<Tproto, Tstate, Tmessage> {

View file

@ -22,13 +22,11 @@ mod pingpong {
pong: mk_packet::<pong>()
}
};
unsafe {
buffer.data.ping.header.set_buffer(buffer);
buffer.data.pong.header.set_buffer(buffer);
do pipes::entangle_buffer(buffer) |buffer, data| {
data.ping.set_buffer(buffer);
data.pong.set_buffer(buffer);
ptr::addr_of(data.ping)
}
let client = send_packet_buffered(ptr::addr_of(buffer.data.ping));
let server = recv_packet_buffered(ptr::addr_of(buffer.data.ping));
(client, server)
}
enum ping = server::pong;
enum pong = client::ping;