1 //! Abstraction over blocking and unblocking the current thread. 2 //! 3 //! Provides an abstraction over blocking the current thread. This is similar to 4 //! the park / unpark constructs provided by `std` but made generic. This allows 5 //! embedding custom functionality to perform when the thread is blocked. 6 //! 7 //! A blocked `Park` instance is unblocked by calling `unpark` on its 8 //! `Unpark` handle. 9 //! 10 //! The `ParkThread` struct implements `Park` using `thread::park` to put the 11 //! thread to sleep. The Tokio reactor also implements park, but uses 12 //! `mio::Poll` to block the thread instead. 13 //! 14 //! The `Park` trait is composable. A timer implementation might decorate a 15 //! `Park` implementation by checking if any timeouts have elapsed after the 16 //! inner `Park` implementation unblocks. 17 //! 18 //! # Model 19 //! 20 //! Conceptually, each `Park` instance has an associated token, which is 21 //! initially not present: 22 //! 23 //! * The `park` method blocks the current thread unless or until the token is 24 //! available, at which point it atomically consumes the token. 25 //! * The `unpark` method atomically makes the token available if it wasn't 26 //! already. 27 //! 28 //! Some things to note: 29 //! 30 //! * If `unpark` is called before `park`, the next call to `park` will 31 //! **not** block the thread. 32 //! * **Spurious** wakeups are permitted, i.e., the `park` method may unblock 33 //! even if `unpark` was not called. 34 //! * `park_timeout` does the same as `park` but allows specifying a maximum 35 //! time to block the thread for. 36 37 cfg_rt! { 38 pub(crate) mod either; 39 } 40 41 #[cfg(any(feature = "rt", feature = "sync"))] 42 pub(crate) mod thread; 43 44 use std::fmt::Debug; 45 use std::sync::Arc; 46 use std::time::Duration; 47 48 /// Blocks the current thread. 49 pub(crate) trait Park { 50 /// Unpark handle type for the `Park` implementation. 51 type Unpark: Unpark; 52 53 /// Error returned by `park`. 54 type Error: Debug; 55 56 /// Gets a new `Unpark` handle associated with this `Park` instance. unpark(&self) -> Self::Unpark57 fn unpark(&self) -> Self::Unpark; 58 59 /// Blocks the current thread unless or until the token is available. 60 /// 61 /// A call to `park` does not guarantee that the thread will remain blocked 62 /// forever, and callers should be prepared for this possibility. This 63 /// function may wakeup spuriously for any reason. 64 /// 65 /// # Panics 66 /// 67 /// This function **should** not panic, but ultimately, panics are left as 68 /// an implementation detail. Refer to the documentation for the specific 69 /// `Park` implementation. park(&mut self) -> Result<(), Self::Error>70 fn park(&mut self) -> Result<(), Self::Error>; 71 72 /// Parks the current thread for at most `duration`. 73 /// 74 /// This function is the same as `park` but allows specifying a maximum time 75 /// to block the thread for. 76 /// 77 /// Same as `park`, there is no guarantee that the thread will remain 78 /// blocked for any amount of time. Spurious wakeups are permitted for any 79 /// reason. 80 /// 81 /// # Panics 82 /// 83 /// This function **should** not panic, but ultimately, panics are left as 84 /// an implementation detail. Refer to the documentation for the specific 85 /// `Park` implementation. park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error>86 fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error>; 87 88 /// Releases all resources holded by the parker for proper leak-free shutdown. shutdown(&mut self)89 fn shutdown(&mut self); 90 } 91 92 /// Unblock a thread blocked by the associated `Park` instance. 93 pub(crate) trait Unpark: Sync + Send + 'static { 94 /// Unblocks a thread that is blocked by the associated `Park` handle. 95 /// 96 /// Calling `unpark` atomically makes available the unpark token, if it is 97 /// not already available. 98 /// 99 /// # Panics 100 /// 101 /// This function **should** not panic, but ultimately, panics are left as 102 /// an implementation detail. Refer to the documentation for the specific 103 /// `Unpark` implementation. unpark(&self)104 fn unpark(&self); 105 } 106 107 impl Unpark for Box<dyn Unpark> { unpark(&self)108 fn unpark(&self) { 109 (**self).unpark() 110 } 111 } 112 113 impl Unpark for Arc<dyn Unpark> { unpark(&self)114 fn unpark(&self) { 115 (**self).unpark() 116 } 117 } 118