diff --git a/src/test/auxiliary/test_comm.rs b/src/test/auxiliary/test_comm.rs new file mode 100644 index 00000000000..48083fdf3f4 --- /dev/null +++ b/src/test/auxiliary/test_comm.rs @@ -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 { + port_t(@port_ptr) +} + +#[doc = "Constructs a port"] +fn port() -> port { + port_t(@port_ptr(rustrt::new_port(sys::size_of::() as size_t))) +} + +class port_ptr { + 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_::(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(p: port) -> T { recv_((**p).po) } + + +#[doc = "Receive on a raw port pointer"] +fn recv_(p: *rust_port) -> T { + let yield = 0u; + let yieldp = ptr::addr_of(yield); + let mut res; + res = rusti::init::(); + 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; +} + + diff --git a/src/test/run-pass/leaky_comm.rs b/src/test/run-pass/leaky_comm.rs new file mode 100644 index 00000000000..24dedd35785 --- /dev/null +++ b/src/test/run-pass/leaky_comm.rs @@ -0,0 +1,18 @@ +// aux-build:test_comm.rs + +use test_comm; + +fn main() { + let p = test_comm::port(); + + alt none:: { + none {} + some(_) { + if test_comm::recv(p) == 0 { + #error("floop"); + } + else { + #error("bloop"); + } + }} +} \ No newline at end of file