1 use crate::{sys, Registry, Token};
2 
3 use 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)]
78 pub struct Waker {
79     inner: sys::Waker,
80 }
81 
82 impl Waker {
83     /// Create a new `Waker`.
new(registry: &Registry, token: Token) -> io::Result<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 { inner })
88     }
89 
90     /// Wake up the [`Poll`] associated with this `Waker`.
91     ///
92     /// [`Poll`]: struct.Poll.html
wake(&self) -> io::Result<()>93     pub fn wake(&self) -> io::Result<()> {
94         self.inner.wake()
95     }
96 }
97