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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
//! Abstraction over blocking and unblocking the current thread. //! //! Provides an abstraction over blocking the current thread. This is similar to //! the park / unpark constructs provided by `std` but made generic. This allows //! embedding custom functionality to perform when the thread is blocked. //! //! A blocked `Park` instance is unblocked by calling `unpark` on its //! `Unpark` handle. //! //! The `ParkThread` struct implements `Park` using `thread::park` to put the //! thread to sleep. The Tokio reactor also implements park, but uses //! `mio::Poll` to block the thread instead. //! //! The `Park` trait is composable. A timer implementation might decorate a //! `Park` implementation by checking if any timeouts have elapsed after the //! inner `Park` implementation unblocks. //! //! # Model //! //! Conceptually, each `Park` instance has an associated token, which is //! initially not present: //! //! * The `park` method blocks the current thread unless or until the token is //! available, at which point it atomically consumes the token. //! * The `unpark` method atomically makes the token available if it wasn't //! already. //! //! Some things to note: //! //! * If `unpark` is called before `park`, the next call to `park` will //! **not** block the thread. //! * **Spurious** wakeups are permitted, i.e., the `park` method may unblock //! even if `unpark` was not called. //! * `park_timeout` does the same as `park` but allows specifying a maximum //! time to block the thread for. cfg_rt! { pub(crate) mod either; } #[cfg(any(feature = "rt", feature = "sync"))] pub(crate) mod thread; use std::sync::Arc; use std::time::Duration; /// Block the current thread. pub(crate) trait Park { /// Unpark handle type for the `Park` implementation. type Unpark: Unpark; /// Error returned by `park` type Error; /// Gets a new `Unpark` handle associated with this `Park` instance. fn unpark(&self) -> Self::Unpark; /// Blocks the current thread unless or until the token is available. /// /// A call to `park` does not guarantee that the thread will remain blocked /// forever, and callers should be prepared for this possibility. This /// function may wakeup spuriously for any reason. /// /// # Panics /// /// This function **should** not panic, but ultimately, panics are left as /// an implementation detail. Refer to the documentation for the specific /// `Park` implementation fn park(&mut self) -> Result<(), Self::Error>; /// Parks the current thread for at most `duration`. /// /// This function is the same as `park` but allows specifying a maximum time /// to block the thread for. /// /// Same as `park`, there is no guarantee that the thread will remain /// blocked for any amount of time. Spurious wakeups are permitted for any /// reason. /// /// # Panics /// /// This function **should** not panic, but ultimately, panics are left as /// an implementation detail. Refer to the documentation for the specific /// `Park` implementation fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error>; /// Release all resources holded by the parker for proper leak-free shutdown fn shutdown(&mut self); } /// Unblock a thread blocked by the associated `Park` instance. pub(crate) trait Unpark: Sync + Send + 'static { /// Unblocks a thread that is blocked by the associated `Park` handle. /// /// Calling `unpark` atomically makes available the unpark token, if it is /// not already available. /// /// # Panics /// /// This function **should** not panic, but ultimately, panics are left as /// an implementation detail. Refer to the documentation for the specific /// `Unpark` implementation fn unpark(&self); } impl Unpark for Box<dyn Unpark> { fn unpark(&self) { (**self).unpark() } } impl Unpark for Arc<dyn Unpark> { fn unpark(&self) { (**self).unpark() } }