Skip to content

Commit 09af02c

Browse files
committed
---
yaml --- r: 14328 b: refs/heads/try c: 601f714 h: refs/heads/master v: v3
1 parent 3b7ae02 commit 09af02c

File tree

2 files changed

+122
-2
lines changed

2 files changed

+122
-2
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@
22
refs/heads/master: 61b1875c16de39c166b0f4d54bba19f9c6777d1a
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 4a81779abd786ff22d71434c6d9a5917ea4cdfff
5-
refs/heads/try: b2cfb7ef8262ebe47514f016f59054ebcfe15d61
5+
refs/heads/try: 601f7144d842dca97440d34774b5ae4c839a43c4
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105

branches/try/src/libcore/comm.rs

Lines changed: 121 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import task;
2727
export send;
2828
export recv;
2929
export peek;
30+
export select2;
3031
export chan::{};
3132
export port::{};
3233

@@ -46,10 +47,14 @@ native mod rustrt {
4647
fn port_recv(dptr: *uint, po: *rust_port,
4748
yield: *ctypes::uintptr_t,
4849
killed: *ctypes::uintptr_t);
50+
fn rust_port_select(dptr: **rust_port, ports: **rust_port,
51+
n_ports: ctypes::size_t,
52+
yield: *ctypes::uintptr_t);
4953
}
5054

5155
#[abi = "rust-intrinsic"]
5256
native mod rusti {
57+
// FIXME: This should probably not take a boxed closure
5358
fn call_with_retptr<T: send>(&&f: fn@(*uint)) -> T;
5459
}
5560

@@ -154,6 +159,45 @@ fn recv_<T: send>(p: *rust_port) -> T {
154159
ret res;
155160
}
156161

162+
#[doc = "Receive on one of two ports"]
163+
fn select2<A: send, B: send>(
164+
p_a: port<A>, p_b: port<B>
165+
) -> either::t<A, B> unsafe {
166+
167+
fn select(dptr: **rust_port, ports: **rust_port,
168+
n_ports: ctypes::size_t, yield: *ctypes::uintptr_t) {
169+
rustrt::rust_port_select(dptr, ports, n_ports, yield)
170+
}
171+
172+
let ports = [];
173+
ports += [***p_a, ***p_b];
174+
let n_ports = 2 as ctypes::size_t;
175+
let yield = 0u;
176+
let yieldp = ptr::addr_of(yield);
177+
178+
let resport: *rust_port = vec::as_buf(ports) {|ports|
179+
rusti::call_with_retptr {|retptr|
180+
select(unsafe::reinterpret_cast(retptr), ports, n_ports, yieldp)
181+
}
182+
};
183+
184+
if yield != 0u {
185+
// Wait for data
186+
task::yield();
187+
}
188+
189+
// Now we know the port we're supposed to receive from
190+
assert resport != ptr::null();
191+
192+
if resport == ***p_a {
193+
either::left(recv(p_a))
194+
} else if resport == ***p_b {
195+
either::right(recv(p_b))
196+
} else {
197+
fail "unexpected result from rust_port_select";
198+
}
199+
}
200+
157201
#[doc = "Returns true if there are messages available"]
158202
fn peek<T: send>(p: port<T>) -> bool {
159203
rustrt::rust_port_size(***p) != 0u as ctypes::size_t
@@ -218,4 +262,80 @@ fn test_peek() {
218262
assert peek(po);
219263
recv(po);
220264
assert !peek(po);
221-
}
265+
}
266+
267+
#[test]
268+
fn test_select2_available() {
269+
let po_a = port();
270+
let po_b = port();
271+
let ch_a = chan(po_a);
272+
let ch_b = chan(po_b);
273+
274+
send(ch_a, "a");
275+
276+
assert select2(po_a, po_b) == either::left("a");
277+
278+
send(ch_b, "b");
279+
280+
assert select2(po_a, po_b) == either::right("b");
281+
}
282+
283+
#[test]
284+
fn test_select2_rendezvous() {
285+
let po_a = port();
286+
let po_b = port();
287+
let ch_a = chan(po_a);
288+
let ch_b = chan(po_b);
289+
290+
iter::repeat(10u) {||
291+
task::spawn {||
292+
iter::repeat(10u) {|| task::yield() }
293+
send(ch_a, "a");
294+
};
295+
296+
assert select2(po_a, po_b) == either::left("a");
297+
298+
task::spawn {||
299+
iter::repeat(10u) {|| task::yield() }
300+
send(ch_b, "b");
301+
};
302+
303+
assert select2(po_a, po_b) == either::right("b");
304+
}
305+
}
306+
307+
#[test]
308+
fn test_select2_stress() {
309+
let po_a = port();
310+
let po_b = port();
311+
let ch_a = chan(po_a);
312+
let ch_b = chan(po_b);
313+
314+
let msgs = 100u;
315+
let times = 4u;
316+
317+
iter::repeat(times) {||
318+
task::spawn {||
319+
iter::repeat(msgs) {||
320+
send(ch_a, "a")
321+
}
322+
};
323+
task::spawn {||
324+
iter::repeat(msgs) {||
325+
send(ch_b, "b")
326+
}
327+
};
328+
}
329+
330+
let as = 0;
331+
let bs = 0;
332+
iter::repeat(msgs * times * 2u) {||
333+
alt check select2(po_a, po_b) {
334+
either::left("a") { as += 1 }
335+
either::right("b") { bs += 1 }
336+
}
337+
}
338+
339+
assert as == 400;
340+
assert bs == 400;
341+
}

0 commit comments

Comments
 (0)