summaryrefslogtreecommitdiffstats
path: root/third_party/rust/mio/src/sys/windows/awakener.rs
blob: c913bc93f8a63b906c978c729e6d97688dcf98c4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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(())
    }
}