1use crate::{sys, Registry, Token};
2
3use std::io;
4
5/// Waker allows cross-thread waking of [`Poll`].
6///
7/// When created it will cause events with [`readable`] readiness and the
8/// provided `token` if [`wake`] is called, possibly from another thread.
9///
10/// [`Poll`]: struct.Poll.html
11/// [`readable`]: ./event/struct.Event.html#method.is_readable
12/// [`wake`]: struct.Waker.html#method.wake
13///
14/// # Notes
15///
16/// `Waker` events are only guaranteed to be delivered while the `Waker` value
17/// is alive.
18///
19/// Only a single `Waker` can be active per [`Poll`], if multiple threads need
20/// access to the `Waker` it can be shared via for example an `Arc`. What
21/// happens if multiple `Waker`s are registered with the same `Poll` is
22/// unspecified.
23///
24/// # Implementation notes
25///
26/// On platforms that support kqueue this will use the `EVFILT_USER` event
27/// filter, see [implementation notes of `Poll`] to see what platforms support
28/// kqueue. On Linux it uses [eventfd].
29///
30/// [implementation notes of `Poll`]: struct.Poll.html#implementation-notes
31/// [eventfd]: https://man7.org/linux/man-pages/man2/eventfd.2.html
32///
33/// # Examples
34///
35/// Wake a [`Poll`] instance from another thread.
36///
37#[cfg_attr(feature = "os-poll", doc = "```")]
38#[cfg_attr(not(feature = "os-poll"), doc = "```ignore")]
39/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
40/// use std::thread;
41/// use std::time::Duration;
42/// use std::sync::Arc;
43///
44/// use mio::{Events, Token, Poll, Waker};
45///
46/// const WAKE_TOKEN: Token = Token(10);
47///
48/// let mut poll = Poll::new()?;
49/// let mut events = Events::with_capacity(2);
50///
51/// let waker = Arc::new(Waker::new(poll.registry(), WAKE_TOKEN)?);
52///
53/// // We need to keep the Waker alive, so we'll create a clone for the
54/// // thread we create below.
55/// let waker1 = waker.clone();
56/// let handle = thread::spawn(move || {
57/// // Working hard, or hardly working?
58/// thread::sleep(Duration::from_millis(500));
59///
60/// // Now we'll wake the queue on the other thread.
61/// waker1.wake().expect("unable to wake");
62/// });
63///
64/// // On our current thread we'll poll for events, without a timeout.
65/// poll.poll(&mut events, None)?;
66///
67/// // After about 500 milliseconds we should be awoken by the other thread and
68/// // get a single event.
69/// assert!(!events.is_empty());
70/// let waker_event = events.iter().next().unwrap();
71/// assert!(waker_event.is_readable());
72/// assert_eq!(waker_event.token(), WAKE_TOKEN);
73/// # handle.join().unwrap();
74/// # Ok(())
75/// # }
76/// ```
77#[derive(Debug)]
78pub struct Waker {
79 inner: sys::Waker,
80}
81
82impl Waker {
83 /// Create a new `Waker`.
84 pub fn new(registry: &Registry, token: Token) -> io::Result<Waker> {
85 #[cfg(debug_assertions)]
86 registry.register_waker();
87 sys::Waker::new(registry.selector(), token).map(|inner: Waker| Waker { inner })
88 }
89
90 /// Wake up the [`Poll`] associated with this `Waker`.
91 ///
92 /// [`Poll`]: struct.Poll.html
93 pub fn wake(&self) -> io::Result<()> {
94 self.inner.wake()
95 }
96}
97