     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
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96

    use crate::{poll, sys, Registry, Token};

    use std::io;

    /// Waker allows cross-thread waking of [`Poll`].
    ///
    /// When created it will cause events with [`readable`] readiness and the
    /// provided `token` if [`wake`] is called, possibly from another thread.
    ///
    /// [`Poll`]: struct.Poll.html
    /// [`readable`]: ./event/struct.Event.html#method.is_readable
    /// [`wake`]: struct.Waker.html#method.wake
    ///
    /// # Notes
    ///
    /// `Waker` events are only guaranteed to be delivered while the `Waker` value
    /// is alive.
    ///
    /// Only a single `Waker` can be active per [`Poll`], if multiple threads need
    /// access to the `Waker` it can be shared via for example an `Arc`. What
    /// happens if multiple `Waker`s are registered with the same `Poll` is
    /// undefined.
    ///
    /// # Implementation notes
    ///
    /// On platforms that support kqueue this will use the `EVFILT_USER` event
    /// filter, see [implementation notes of `Poll`] to see what platforms support
    /// kqueue. On Linux it uses [eventfd].
    ///
    /// [implementation notes of `Poll`]: struct.Poll.html#implementation-notes
    /// [eventfd]: http://man7.org/linux/man-pages/man2/eventfd.2.html
    ///
    /// # Examples
    ///
    /// Wake a [`Poll`] instance from another thread.
    ///
    #[cfg_attr(feature = "os-poll", doc = "```")]
    #[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
    /// use std::thread;
    /// use std::time::Duration;
    /// use std::sync::Arc;
    ///
    /// use mio::{Events, Token, Poll, Waker};
    ///
    /// const WAKE_TOKEN: Token = Token(10);
    ///
    /// let mut poll = Poll::new()?;
    /// let mut events = Events::with_capacity(2);
    ///
    /// let waker = Arc::new(Waker::new(poll.registry(), WAKE_TOKEN)?);
    ///
    /// // We need to keep the Waker alive, so we'll create a clone for the
    /// // thread we create below.
    /// let waker1 = waker.clone();
    /// let handle = thread::spawn(move || {
    ///     // Working hard, or hardly working?
    ///     thread::sleep(Duration::from_millis(500));
    ///
    ///     // Now we'll wake the queue on the other thread.
    ///     waker1.wake().expect("unable to wake");
    /// });
    ///
    /// // On our current thread we'll poll for events, without a timeout.
    /// poll.poll(&mut events, None)?;
    ///
    /// // After about 500 milliseconds we should be awoken by the other thread and
    /// // get a single event.
    /// assert!(!events.is_empty());
    /// let waker_event = events.iter().next().unwrap();
    /// assert!(waker_event.is_readable());
    /// assert_eq!(waker_event.token(), WAKE_TOKEN);
    /// # handle.join().unwrap();
    /// #     Ok(())
    /// # }
    /// ```
    #[derive(Debug)]
    pub struct Waker {
        inner: sys::Waker,
    }

    impl Waker {
        /// Create a new `Waker`.
        pub fn new(registry: &Registry, token: Token) -> io::Result<Waker> {
            #[cfg(debug_assertions)]
            registry.register_waker();
            sys::Waker::new(poll::selector(&registry), token).map(|inner| Waker { inner })
        }

        /// Wake up the [`Poll`] associated with this `Waker`.
        ///
        /// [`Poll`]: struct.Poll.html
        pub fn wake(&self) -> io::Result<()> {
            self.inner.wake()
        }
    }