diff options
Diffstat (limited to 'src/libstd/comm/select.rs')
| -rw-r--r-- | src/libstd/comm/select.rs | 120 |
1 files changed, 106 insertions, 14 deletions
diff --git a/src/libstd/comm/select.rs b/src/libstd/comm/select.rs index b6b35ccc357..e41fa60aa42 100644 --- a/src/libstd/comm/select.rs +++ b/src/libstd/comm/select.rs @@ -60,21 +60,17 @@ use uint; macro_rules! select { ( - $name1:pat = $port1:ident.$meth1:ident() => $code1:expr, - $($name:pat = $port:ident.$meth:ident() => $code:expr),* + $($name:pat = $port:ident.$meth:ident() => $code:expr),+ ) => ({ use std::comm::Select; let sel = Select::new(); - let mut $port1 = sel.handle(&$port1); - $( let mut $port = sel.handle(&$port); )* + $( let mut $port = sel.handle(&$port); )+ unsafe { - $port1.add(); - $( $port.add(); )* + $( $port.add(); )+ } let ret = sel.wait(); - if ret == $port1.id { let $name1 = $port1.$meth1(); $code1 } - $( else if ret == $port.id { let $name = $port.$meth(); $code } )* - else { unreachable!() } + $( if ret == $port.id() { let $name = $port.$meth(); $code } else )+ + { unreachable!() } }) } @@ -94,7 +90,7 @@ pub struct Select { pub struct Handle<'port, T> { /// The ID of this handle, used to compare against the return value of /// `Select::wait()` - id: uint, + priv id: uint, priv selector: &'port Select, priv next: *mut Handle<'static, ()>, priv prev: *mut Handle<'static, ()>, @@ -150,11 +146,16 @@ impl Select { /// Waits for an event on this port set. The returned valus is *not* and /// index, but rather an id. This id can be queried against any active - /// `Handle` structures (each one has a public `id` field). The handle with + /// `Handle` structures (each one has an `id` method). The handle with /// the matching `id` will have some sort of event available on it. The /// event could either be that data is available or the corresponding /// channel has been closed. pub fn wait(&self) -> uint { + self.wait2(false) + } + + /// Helper method for skipping the preflight checks during testing + fn wait2(&self, do_preflight_checks: bool) -> uint { // Note that this is currently an inefficient implementation. We in // theory have knowledge about all ports in the set ahead of time, so // this method shouldn't really have to iterate over all of them yet @@ -179,7 +180,7 @@ impl Select { let mut amt = 0; for p in self.iter() { amt += 1; - if (*p).packet.can_recv() { + if do_preflight_checks && (*p).packet.can_recv() { return (*p).id; } } @@ -242,6 +243,10 @@ impl Select { } impl<'port, T: Send> Handle<'port, T> { + /// Retrieve the id of this handle. + #[inline] + pub fn id(&self) -> uint { self.id } + /// Receive a value on the underlying port. Has the same semantics as /// `Port.recv` pub fn recv(&mut self) -> T { self.port.recv() } @@ -355,7 +360,7 @@ mod test { ) drop(c2); select! ( - bar = p2.recv_opt() => { assert_eq!(bar, None); }, + bar = p2.recv_opt() => { assert_eq!(bar, None); } ) }) @@ -507,7 +512,7 @@ mod test { let (p2, c2) = Chan::<()>::new(); let (p, c) = Chan::new(); spawn(proc() { - let mut s = Select::new(); + let s = Select::new(); let mut h1 = s.handle(&p1); let mut h2 = s.handle(&p2); unsafe { h2.add(); } @@ -521,4 +526,91 @@ mod test { c2.send(()); p.recv(); }) + + test!(fn preflight1() { + let (p, c) = Chan::new(); + c.send(()); + select!( + () = p.recv() => {} + ) + }) + + test!(fn preflight2() { + let (p, c) = Chan::new(); + c.send(()); + c.send(()); + select!( + () = p.recv() => {} + ) + }) + + test!(fn preflight3() { + let (p, c) = Chan::new(); + drop(c.clone()); + c.send(()); + select!( + () = p.recv() => {} + ) + }) + + test!(fn preflight4() { + let (p, c) = Chan::new(); + c.send(()); + let s = Select::new(); + let mut h = s.handle(&p); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); + }) + + test!(fn preflight5() { + let (p, c) = Chan::new(); + c.send(()); + c.send(()); + let s = Select::new(); + let mut h = s.handle(&p); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); + }) + + test!(fn preflight6() { + let (p, c) = Chan::new(); + drop(c.clone()); + c.send(()); + let s = Select::new(); + let mut h = s.handle(&p); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); + }) + + test!(fn preflight7() { + let (p, c) = Chan::<()>::new(); + drop(c); + let s = Select::new(); + let mut h = s.handle(&p); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); + }) + + test!(fn preflight8() { + let (p, c) = Chan::new(); + c.send(()); + drop(c); + p.recv(); + let s = Select::new(); + let mut h = s.handle(&p); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); + }) + + test!(fn preflight9() { + let (p, c) = Chan::new(); + drop(c.clone()); + c.send(()); + drop(c); + p.recv(); + let s = Select::new(); + let mut h = s.handle(&p); + unsafe { h.add(); } + assert_eq!(s.wait2(false), h.id); + }) } |
