1 use {io, poll, Evented, Ready, Poll, PollOpt, Token};
2 use zircon;
3 use std::sync::{Arc, Mutex, Weak};
4 
5 pub struct Awakener {
6     /// Token and weak reference to the port on which Awakener was registered.
7     ///
8     /// When `Awakener::wakeup` is called, these are used to send a wakeup message to the port.
9     inner: Mutex<Option<(Token, Weak<zircon::Port>)>>,
10 }
11 
12 impl Awakener {
13     /// Create a new `Awakener`.
14     pub fn new() -> io::Result<Awakener> {
15         Ok(Awakener {
16             inner: Mutex::new(None)
17         })
18     }
19 
20     /// Send a wakeup signal to the `Selector` on which the `Awakener` was registered.
21     pub fn wakeup(&self) -> io::Result<()> {
22         let inner_locked = self.inner.lock().unwrap();
23         let &(token, ref weak_port) =
24             inner_locked.as_ref().expect("Called wakeup on unregistered awakener.");
25 
26         let port = weak_port.upgrade().expect("Tried to wakeup a closed port.");
27 
28         let status = 0; // arbitrary
29         let packet = zircon::Packet::from_user_packet(
30             token.0 as u64, status, zircon::UserPacket::from_u8_array([0; 32]));
31 
32         Ok(port.queue(&packet)?)
33     }
34 
35     pub fn cleanup(&self) {}
36 }
37 
38 impl Evented for Awakener {
39     fn register(&self,
40                 poll: &Poll,
41                 token: Token,
42                 _events: Ready,
43                 _opts: PollOpt) -> io::Result<()>
44     {
45         let mut inner_locked = self.inner.lock().unwrap();
46         if inner_locked.is_some() {
47             panic!("Called register on already-registered Awakener.");
48         }
49         *inner_locked = Some((token, Arc::downgrade(poll::selector(poll).port())));
50 
51         Ok(())
52     }
53 
54     fn reregister(&self,
55                   poll: &Poll,
56                   token: Token,
57                   _events: Ready,
58                   _opts: PollOpt) -> io::Result<()>
59     {
60         let mut inner_locked = self.inner.lock().unwrap();
61         *inner_locked = Some((token, Arc::downgrade(poll::selector(poll).port())));
62 
63         Ok(())
64     }
65 
66     fn deregister(&self, _poll: &Poll) -> io::Result<()>
67     {
68         let mut inner_locked = self.inner.lock().unwrap();
69         *inner_locked = None;
70 
71         Ok(())
72     }
73 }