Test case for previous commit
(basically a stripped-down version of comm, and a "driver" that constructs a new port)
This commit is contained in:
parent
aa9d2d88d3
commit
eadd74b5b6
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
Minimized version of core::comm (with still-local modifications
|
||||
to turn a resource into a class) for testing.
|
||||
|
||||
Could probably be more minimal.
|
||||
*/
|
||||
|
||||
import libc::size_t;
|
||||
|
||||
export port::{};
|
||||
export port;
|
||||
export recv;
|
||||
|
||||
|
||||
#[doc = "
|
||||
A communication endpoint that can receive messages
|
||||
|
||||
Each port has a unique per-task identity and may not be replicated or
|
||||
transmitted. If a port value is copied, both copies refer to the same
|
||||
port. Ports may be associated with multiple `chan`s.
|
||||
"]
|
||||
enum port<T: send> {
|
||||
port_t(@port_ptr<T>)
|
||||
}
|
||||
|
||||
#[doc = "Constructs a port"]
|
||||
fn port<T: send>() -> port<T> {
|
||||
port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>() as size_t)))
|
||||
}
|
||||
|
||||
class port_ptr<T:send> {
|
||||
let po: *rust_port;
|
||||
new(po: *rust_port) {
|
||||
#debug("in the port_ptr constructor");
|
||||
self.po = po; }
|
||||
drop unsafe {
|
||||
#debug("in the port_ptr destructor");
|
||||
task::unkillable {||
|
||||
let yield = 0u;
|
||||
let yieldp = ptr::addr_of(yield);
|
||||
rustrt::rust_port_begin_detach(self.po, yieldp);
|
||||
if yield != 0u {
|
||||
task::yield();
|
||||
}
|
||||
rustrt::rust_port_end_detach(self.po);
|
||||
|
||||
while rustrt::rust_port_size(self.po) > 0u as size_t {
|
||||
recv_::<T>(self.po);
|
||||
}
|
||||
rustrt::del_port(self.po);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[doc = "
|
||||
Receive from a port. If no data is available on the port then the
|
||||
task will block until data becomes available.
|
||||
"]
|
||||
fn recv<T: send>(p: port<T>) -> T { recv_((**p).po) }
|
||||
|
||||
|
||||
#[doc = "Receive on a raw port pointer"]
|
||||
fn recv_<T: send>(p: *rust_port) -> T {
|
||||
let yield = 0u;
|
||||
let yieldp = ptr::addr_of(yield);
|
||||
let mut res;
|
||||
res = rusti::init::<T>();
|
||||
rustrt::port_recv(ptr::addr_of(res) as *uint, p, yieldp);
|
||||
|
||||
if yield != 0u {
|
||||
// Data isn't available yet, so res has not been initialized.
|
||||
task::yield();
|
||||
} else {
|
||||
// In the absense of compiler-generated preemption points
|
||||
// this is a good place to yield
|
||||
task::yield();
|
||||
}
|
||||
ret res;
|
||||
}
|
||||
|
||||
|
||||
/* Implementation details */
|
||||
|
||||
|
||||
enum rust_port {}
|
||||
|
||||
type port_id = int;
|
||||
|
||||
#[abi = "cdecl"]
|
||||
native mod rustrt {
|
||||
|
||||
fn new_port(unit_sz: libc::size_t) -> *rust_port;
|
||||
fn del_port(po: *rust_port);
|
||||
fn rust_port_begin_detach(po: *rust_port,
|
||||
yield: *libc::uintptr_t);
|
||||
fn rust_port_end_detach(po: *rust_port);
|
||||
fn rust_port_size(po: *rust_port) -> libc::size_t;
|
||||
fn port_recv(dptr: *uint, po: *rust_port,
|
||||
yield: *libc::uintptr_t);
|
||||
}
|
||||
|
||||
#[abi = "rust-intrinsic"]
|
||||
native mod rusti {
|
||||
fn init<T>() -> T;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
// aux-build:test_comm.rs
|
||||
|
||||
use test_comm;
|
||||
|
||||
fn main() {
|
||||
let p = test_comm::port();
|
||||
|
||||
alt none::<int> {
|
||||
none {}
|
||||
some(_) {
|
||||
if test_comm::recv(p) == 0 {
|
||||
#error("floop");
|
||||
}
|
||||
else {
|
||||
#error("bloop");
|
||||
}
|
||||
}}
|
||||
}
|
Loading…
Reference in New Issue