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