summaryrefslogtreecommitdiffstats
path: root/third_party/rust/mio-0.6.23/src/sys/fuchsia/awakener.rs
blob: 19bc7624290680dde041842eb766185f8015bc2e (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
67
68
69
70
71
72
73
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(())
    }
}