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_resource_drivers! { 38 mod either; 39 pub(crate) use self::either::Either; 40 } 41 42 mod thread; 43 pub(crate) use self::thread::ParkThread; 44 45 cfg_block_on! { 46 pub(crate) use self::thread::{CachedParkThread, ParkError}; 47 } 48 49 use std::sync::Arc; 50 use std::time::Duration; 51 52 /// Block the current thread. 53 pub(crate) trait Park { 54 /// Unpark handle type for the `Park` implementation. 55 type Unpark: Unpark; 56 57 /// Error returned by `park` 58 type Error; 59 60 /// Gets a new `Unpark` handle associated with this `Park` instance. unpark(&self) -> Self::Unpark61 fn unpark(&self) -> Self::Unpark; 62 63 /// Blocks the current thread unless or until the token is available. 64 /// 65 /// A call to `park` does not guarantee that the thread will remain blocked 66 /// forever, and callers should be prepared for this possibility. This 67 /// function may wakeup spuriously for any reason. 68 /// 69 /// # Panics 70 /// 71 /// This function **should** not panic, but ultimately, panics are left as 72 /// an implementation detail. Refer to the documentation for the specific 73 /// `Park` implementation park(&mut self) -> Result<(), Self::Error>74 fn park(&mut self) -> Result<(), Self::Error>; 75 76 /// Parks the current thread for at most `duration`. 77 /// 78 /// This function is the same as `park` but allows specifying a maximum time 79 /// to block the thread for. 80 /// 81 /// Same as `park`, there is no guarantee that the thread will remain 82 /// blocked for any amount of time. Spurious wakeups are permitted for any 83 /// reason. 84 /// 85 /// # Panics 86 /// 87 /// This function **should** not panic, but ultimately, panics are left as 88 /// an implementation detail. Refer to the documentation for the specific 89 /// `Park` implementation park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error>90 fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error>; 91 } 92 93 /// Unblock a thread blocked by the associated `Park` instance. 94 pub(crate) trait Unpark: Sync + Send + 'static { 95 /// Unblocks a thread that is blocked by the associated `Park` handle. 96 /// 97 /// Calling `unpark` atomically makes available the unpark token, if it is 98 /// not already available. 99 /// 100 /// # Panics 101 /// 102 /// This function **should** not panic, but ultimately, panics are left as 103 /// an implementation detail. Refer to the documentation for the specific 104 /// `Unpark` implementation unpark(&self)105 fn unpark(&self); 106 } 107 108 impl Unpark for Box<dyn Unpark> { unpark(&self)109 fn unpark(&self) { 110 (**self).unpark() 111 } 112 } 113 114 impl Unpark for Arc<dyn Unpark> { unpark(&self)115 fn unpark(&self) { 116 (**self).unpark() 117 } 118 } 119