mio_st/poll/awakener.rs
1use std::io;
2
3use crate::event::EventedId;
4use crate::poll::Poller;
5use crate::sys;
6
7/// Awakener allows cross-thread waking of a `Poller` instance.
8///
9/// When created it will cause events with [`Ready::READABLE`] and the provided
10/// `id` if [`wake`] is called, possibly from another thread.
11///
12/// # Notes
13///
14/// The `Awakener` needs to be kept alive as long as wake up notifications are
15/// required. This is due to an implementation detail where if all copies of the
16/// `Awakener` are dropped it will also drop all wake up notifications from the
17/// system queue, including wake up notifications that have been added before
18/// the `Awakener` that was dropped, resulting the `Poller` instance not being
19/// woken up.
20///
21/// Only a single `Awakener` should active per `Poller` instance, the `Awakener`
22/// can be cloned using [`try_clone`] if more are needed. What happens if
23/// multiple `Awakener`s are registered with the same `Poller` instance is
24/// undefined.
25///
26/// [`Ready::READABLE`]: crate::event::Ready::READABLE
27/// [`wake`]: Awakener::wake
28/// [`try_clone`]: Awakener::try_clone
29///
30/// # Examples
31///
32/// Wake a `Poller` instance from another thread.
33///
34/// ```
35/// # fn main() -> Result<(), Box<std::error::Error>> {
36/// use std::thread;
37/// use std::time::Duration;
38///
39/// use mio_st::event::{Events, EventedId, Ready};
40/// use mio_st::poll::{Poller, Awakener};
41///
42/// const WAKE_ID: EventedId = EventedId(10);
43///
44/// let mut poller = Poller::new()?;
45/// let mut events = Events::new();
46///
47/// let awakener = Awakener::new(&mut poller, WAKE_ID)?;
48/// // We need to keep the Awakener alive, so we'll create a clone for the
49/// // thread we create below.
50/// let awakener1 = awakener.try_clone()?;
51///
52/// let handle = thread::spawn(move || {
53/// // Working hard, or hardly working?
54/// thread::sleep(Duration::from_millis(500));
55///
56/// // Now we'll wake the poller instance on the other thread.
57/// awakener1.wake().expect("unable to wake");
58/// });
59///
60/// // On our current thread we'll poll for events, without a timeout.
61/// poller.poll(&mut events, None)?;
62///
63/// // After about 500 milliseconds we should we awoken by the other thread,
64/// // getting a single event.
65/// assert_eq!(events.len(), 1);
66/// let event = (&mut events).next().unwrap();
67/// assert_eq!(event.id(), WAKE_ID);
68/// assert_eq!(event.readiness(), Ready::READABLE);
69///
70/// # handle.join().unwrap();
71/// # Ok(())
72/// # }
73/// ```
74#[derive(Debug)]
75pub struct Awakener {
76 inner: sys::Awakener,
77}
78
79impl Awakener {
80 /// Create a new `Awakener`.
81 pub fn new(poller: &mut Poller, id: EventedId) -> io::Result<Awakener> {
82 sys::Awakener::new(poller.selector(), id).map(|inner| Awakener { inner })
83 }
84
85 /// Attempts to clone the `Awakener`.
86 pub fn try_clone(&self) -> io::Result<Awakener> {
87 self.inner.try_clone().map(|inner| Awakener { inner })
88 }
89
90 /// Wake up the [`Poller`](Poller) instance associated with this `Awakener`.
91 pub fn wake(&self) -> io::Result<()> {
92 self.inner.wake()
93 }
94}