Skip to content

Commit 585ec62

Browse files
committed
add Park trait
1 parent 83768aa commit 585ec62

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

futures-executor/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,8 @@ pub use crate::thread_pool::{ThreadPool, ThreadPoolBuilder};
2626
mod enter;
2727
#[cfg(feature = "std")]
2828
pub use crate::enter::{enter, Enter, EnterError};
29+
30+
#[cfg(feature = "std")]
31+
mod park;
32+
#[cfg(feature = "std")]
33+
pub use crate::park::{Park, ParkDuration};

futures-executor/src/park.rs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
use crate::enter::Enter;
2+
use std::time::Duration;
3+
use futures_util::task::WakerRef;
4+
5+
/// Determines how long `park` will block
6+
#[derive(Clone, Copy, Debug)]
7+
pub enum ParkDuration {
8+
/// Don't block at all
9+
Poll,
10+
/// Block until explicit (possibly spurious) unpark
11+
Block,
12+
/// Block at most for given Duration; might get rounded up to some
13+
/// minimum "sleepable" value by `Park` implementation if timeout is
14+
/// too small (including zero).
15+
Timeout(Duration),
16+
}
17+
18+
impl ParkDuration {
19+
/// Create a new duration specification which doesn't block longer
20+
/// than the passed limit.
21+
pub fn limit(self, max_duration: Duration) -> Self {
22+
match self {
23+
ParkDuration::Poll => ParkDuration::Poll,
24+
ParkDuration::Block => ParkDuration::Timeout(max_duration),
25+
ParkDuration::Timeout(d) => ParkDuration::Timeout(std::cmp::min(d, max_duration)),
26+
}
27+
}
28+
}
29+
30+
/// Convert zero duration to `Poll`; other durations are wrapped in
31+
/// `Timeout(..)`.
32+
impl From<Duration> for ParkDuration {
33+
fn from(duration: Duration) -> Self {
34+
if duration == Duration::from_secs(0) {
35+
ParkDuration::Poll
36+
} else {
37+
ParkDuration::Timeout(duration)
38+
}
39+
}
40+
}
41+
42+
/// Convert `None` to `Block`, zero durations to `Poll` and other
43+
/// durations are wrapped in `Timeout(..)`.
44+
impl From<Option<Duration>> for ParkDuration {
45+
fn from(duration: Option<Duration>) -> Self {
46+
match duration {
47+
Some(duration) => ParkDuration::from(duration),
48+
None => ParkDuration::Block,
49+
}
50+
}
51+
}
52+
53+
/// Block the current thread.
54+
pub trait Park {
55+
/// Error returned by `park`
56+
type Error;
57+
58+
/// Get a new `Waker` associated with this `Park` instance.
59+
fn waker(&self) -> WakerRef<'_>;
60+
61+
/// Block the current thread unless or until the token is available;
62+
/// `duration` determines for how long.
63+
///
64+
/// A call to `park` does not guarantee that the thread will remain
65+
/// blocked forever, and callers should be prepared for this
66+
/// possibility. This function may wakeup spuriously for any reason.
67+
///
68+
/// # Panics
69+
///
70+
/// This function **should** not panic, but ultimately, panics are
71+
/// left as an implementation detail. Refer to the documentation for
72+
/// the specific `Park` implementation
73+
fn park(&mut self, enter: &mut Enter, duration: ParkDuration) -> Result<(), Self::Error>;
74+
}
75+
76+
impl<P: Park> Park for &'_ mut P {
77+
type Error = P::Error;
78+
79+
fn waker(&self) -> WakerRef<'_> {
80+
(**self).waker()
81+
}
82+
83+
fn park(&mut self, enter: &mut Enter, duration: ParkDuration) -> Result<(), Self::Error> {
84+
(**self).park(enter, duration)
85+
}
86+
}

0 commit comments

Comments
 (0)