Skip to content

Commit eadd74b

Browse files
committed
Test case for previous commit
(basically a stripped-down version of comm, and a "driver" that constructs a new port)
1 parent aa9d2d8 commit eadd74b

File tree

2 files changed

+126
-0
lines changed

2 files changed

+126
-0
lines changed

src/test/auxiliary/test_comm.rs

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*
2+
Minimized version of core::comm (with still-local modifications
3+
to turn a resource into a class) for testing.
4+
5+
Could probably be more minimal.
6+
*/
7+
8+
import libc::size_t;
9+
10+
export port::{};
11+
export port;
12+
export recv;
13+
14+
15+
#[doc = "
16+
A communication endpoint that can receive messages
17+
18+
Each port has a unique per-task identity and may not be replicated or
19+
transmitted. If a port value is copied, both copies refer to the same
20+
port. Ports may be associated with multiple `chan`s.
21+
"]
22+
enum port<T: send> {
23+
port_t(@port_ptr<T>)
24+
}
25+
26+
#[doc = "Constructs a port"]
27+
fn port<T: send>() -> port<T> {
28+
port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>() as size_t)))
29+
}
30+
31+
class port_ptr<T:send> {
32+
let po: *rust_port;
33+
new(po: *rust_port) {
34+
#debug("in the port_ptr constructor");
35+
self.po = po; }
36+
drop unsafe {
37+
#debug("in the port_ptr destructor");
38+
task::unkillable {||
39+
let yield = 0u;
40+
let yieldp = ptr::addr_of(yield);
41+
rustrt::rust_port_begin_detach(self.po, yieldp);
42+
if yield != 0u {
43+
task::yield();
44+
}
45+
rustrt::rust_port_end_detach(self.po);
46+
47+
while rustrt::rust_port_size(self.po) > 0u as size_t {
48+
recv_::<T>(self.po);
49+
}
50+
rustrt::del_port(self.po);
51+
}
52+
}
53+
}
54+
55+
56+
#[doc = "
57+
Receive from a port. If no data is available on the port then the
58+
task will block until data becomes available.
59+
"]
60+
fn recv<T: send>(p: port<T>) -> T { recv_((**p).po) }
61+
62+
63+
#[doc = "Receive on a raw port pointer"]
64+
fn recv_<T: send>(p: *rust_port) -> T {
65+
let yield = 0u;
66+
let yieldp = ptr::addr_of(yield);
67+
let mut res;
68+
res = rusti::init::<T>();
69+
rustrt::port_recv(ptr::addr_of(res) as *uint, p, yieldp);
70+
71+
if yield != 0u {
72+
// Data isn't available yet, so res has not been initialized.
73+
task::yield();
74+
} else {
75+
// In the absense of compiler-generated preemption points
76+
// this is a good place to yield
77+
task::yield();
78+
}
79+
ret res;
80+
}
81+
82+
83+
/* Implementation details */
84+
85+
86+
enum rust_port {}
87+
88+
type port_id = int;
89+
90+
#[abi = "cdecl"]
91+
native mod rustrt {
92+
93+
fn new_port(unit_sz: libc::size_t) -> *rust_port;
94+
fn del_port(po: *rust_port);
95+
fn rust_port_begin_detach(po: *rust_port,
96+
yield: *libc::uintptr_t);
97+
fn rust_port_end_detach(po: *rust_port);
98+
fn rust_port_size(po: *rust_port) -> libc::size_t;
99+
fn port_recv(dptr: *uint, po: *rust_port,
100+
yield: *libc::uintptr_t);
101+
}
102+
103+
#[abi = "rust-intrinsic"]
104+
native mod rusti {
105+
fn init<T>() -> T;
106+
}
107+
108+

src/test/run-pass/leaky_comm.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// aux-build:test_comm.rs
2+
3+
use test_comm;
4+
5+
fn main() {
6+
let p = test_comm::port();
7+
8+
alt none::<int> {
9+
none {}
10+
some(_) {
11+
if test_comm::recv(p) == 0 {
12+
#error("floop");
13+
}
14+
else {
15+
#error("bloop");
16+
}
17+
}}
18+
}

0 commit comments

Comments
 (0)