blob: 19bc7624290680dde041842eb766185f8015bc2e [file] [log] [blame]
use {io, poll, Evented, Ready, Poll, PollOpt, Token};
use zircon;
use std::sync::{Arc, Mutex, Weak};
pub struct Awakener {
/// Token and weak reference to the port on which Awakener was registered.
///
/// When `Awakener::wakeup` is called, these are used to send a wakeup message to the port.
inner: Mutex<Option<(Token, Weak<zircon::Port>)>>,
}
impl Awakener {
/// Create a new `Awakener`.
pub fn new() -> io::Result<Awakener> {
Ok(Awakener {
inner: Mutex::new(None)
})
}
/// Send a wakeup signal to the `Selector` on which the `Awakener` was registered.
pub fn wakeup(&self) -> io::Result<()> {
let inner_locked = self.inner.lock().unwrap();
let &(token, ref weak_port) =
inner_locked.as_ref().expect("Called wakeup on unregistered awakener.");
let port = weak_port.upgrade().expect("Tried to wakeup a closed port.");
let status = 0; // arbitrary
let packet = zircon::Packet::from_user_packet(
token.0 as u64, status, zircon::UserPacket::from_u8_array([0; 32]));
Ok(port.queue(&packet)?)
}
pub fn cleanup(&self) {}
}
impl Evented for Awakener {
fn register(&self,
poll: &Poll,
token: Token,
_events: Ready,
_opts: PollOpt) -> io::Result<()>
{
let mut inner_locked = self.inner.lock().unwrap();
if inner_locked.is_some() {
panic!("Called register on already-registered Awakener.");
}
*inner_locked = Some((token, Arc::downgrade(poll::selector(poll).port())));
Ok(())
}
fn reregister(&self,
poll: &Poll,
token: Token,
_events: Ready,
_opts: PollOpt) -> io::Result<()>
{
let mut inner_locked = self.inner.lock().unwrap();
*inner_locked = Some((token, Arc::downgrade(poll::selector(poll).port())));
Ok(())
}
fn deregister(&self, _poll: &Poll) -> io::Result<()>
{
let mut inner_locked = self.inner.lock().unwrap();
*inner_locked = None;
Ok(())
}
}