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(®istry), 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() } }