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 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
//! 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`][p] instance is unblocked by calling [`unpark`] on its //! [`Unpark`][up] handle. //! //! The [`ParkThread`] struct implements [`Park`][p] using //! [`thread::park`][`std`] to put the thread to sleep. The Tokio reactor also //! implements park, but uses [`mio::Poll`][mio] to block the thread instead. //! //! The [`Park`][p] trait is composable. A timer implementation might decorate a //! [`Park`][p] implementation by checking if any timeouts have elapsed after //! the inner [`Park`][p] implementation unblocks. //! //! # Model //! //! Conceptually, each [`Park`][p] 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. //! //! [`std`]: https://doc.rust-lang.org/std/thread/fn.park.html //! [`thread::park`]: https://doc.rust-lang.org/std/thread/fn.park.html //! [`ParkThread`]: struct.ParkThread.html //! [p]: trait.Park.html //! [`park`]: trait.Park.html#tymethod.park //! [`park_timeout`]: trait.Park.html#tymethod.park_timeout //! [`unpark`]: trait.Unpark.html#tymethod.unpark //! [up]: trait.Unpark.html //! [mio]: https://docs.rs/mio/0.6/mio/struct.Poll.html cfg_resource_drivers! { mod either; pub(crate) use self::either::Either; } mod thread; pub(crate) use self::thread::ParkThread; cfg_blocking_impl! { pub(crate) use self::thread::CachedParkThread; } use std::sync::Arc; use std::time::Duration; /// Block the current thread. /// /// See [module documentation][mod] for more details. /// /// [mod]: ../index.html pub(crate) trait Park { /// Unpark handle type for the `Park` implementation. type Unpark: Unpark; /// Error returned by `park` type Error; /// Get a new `Unpark` handle associated with this `Park` instance. fn unpark(&self) -> Self::Unpark; /// Block 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. /// /// See [module documentation][mod] for more details. /// /// # Panics /// /// This function **should** not panic, but ultimately, panics are left as /// an implementation detail. Refer to the documentation for the specific /// `Park` implementation /// /// [mod]: ../index.html fn park(&mut self) -> Result<(), Self::Error>; /// Park 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. /// /// See [module documentation][mod] for more details. /// /// # Panics /// /// This function **should** not panic, but ultimately, panics are left as /// an implementation detail. Refer to the documentation for the specific /// `Park` implementation /// /// [mod]: ../index.html fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error>; } /// Unblock a thread blocked by the associated [`Park`] instance. /// /// See [module documentation][mod] for more details. /// /// [mod]: ../index.html /// [`Park`]: trait.Park.html pub(crate) trait Unpark: Sync + Send + 'static { /// Unblock a thread that is blocked by the associated `Park` handle. /// /// Calling `unpark` atomically makes available the unpark token, if it is /// not already available. /// /// See [module documentation][mod] for more details. /// /// # Panics /// /// This function **should** not panic, but ultimately, panics are left as /// an implementation detail. Refer to the documentation for the specific /// `Unpark` implementation /// /// [mod]: ../index.html 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() } }