blob: c913bc93f8a63b906c978c729e6d97688dcf98c4 [file] [log] [blame]
use std::sync::Mutex;
use miow::iocp::CompletionStatus;
use {io, poll, Ready, Poll, PollOpt, Token};
use event::Evented;
use sys::windows::Selector;
pub struct Awakener {
inner: Mutex<Option<AwakenerInner>>,
}
struct AwakenerInner {
token: Token,
selector: Selector,
}
impl Awakener {
pub fn new() -> io::Result<Awakener> {
Ok(Awakener {
inner: Mutex::new(None),
})
}
pub fn wakeup(&self) -> io::Result<()> {
// Each wakeup notification has NULL as its `OVERLAPPED` pointer to
// indicate that it's from this awakener and not part of an I/O
// operation. This is specially recognized by the selector.
//
// If we haven't been registered with an event loop yet just silently
// succeed.
if let Some(inner) = self.inner.lock().unwrap().as_ref() {
let status = CompletionStatus::new(0,
usize::from(inner.token),
0 as *mut _);
inner.selector.port().post(status)?;
}
Ok(())
}
pub fn cleanup(&self) {
// noop
}
}
impl Evented for Awakener {
fn register(&self, poll: &Poll, token: Token, events: Ready,
opts: PollOpt) -> io::Result<()> {
assert_eq!(opts, PollOpt::edge());
assert_eq!(events, Ready::readable());
*self.inner.lock().unwrap() = Some(AwakenerInner {
selector: poll::selector(poll).clone_ref(),
token: token,
});
Ok(())
}
fn reregister(&self, poll: &Poll, token: Token, events: Ready,
opts: PollOpt) -> io::Result<()> {
self.register(poll, token, events, opts)
}
fn deregister(&self, _poll: &Poll) -> io::Result<()> {
*self.inner.lock().unwrap() = None;
Ok(())
}
}