• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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