Skip to content
Snippets Groups Projects
Commit c875391e authored by Georgy Moshkin's avatar Georgy Moshkin :speech_balloon:
Browse files

feat: fiber::r#async::timeout::{deadline, IntoTimeout::deadline}

parent f38b2ba5
No related branches found
No related tags found
1 merge request!438Gmoshkin/fiber tweaks & more
......@@ -28,6 +28,8 @@
when doing so.
- `fiber::Cond::wait_deadline` for waiting until `tarantool::time::Instant`
rather than a `Duration`. Uses `fiber::clock` internally.
- `fiber::r#async::timeout::{deadline, IntoTimeout::deadline}` for constraining
futures with an explicit deadline.
- `util::str_eq` function for comparing strings at compile time.
- `define_enum_with_introspection` enum for defining enums with some
introspection facilities including type-safe conversion from integers and
......
......@@ -53,7 +53,7 @@ pub struct Timeout<F> {
/// println!("did not receive value within 10 ms");
/// }
/// ```
#[inline]
#[inline(always)]
pub fn timeout<F: Future>(timeout: Duration, f: F) -> Timeout<F> {
Timeout {
future: f,
......@@ -61,6 +61,15 @@ pub fn timeout<F: Future>(timeout: Duration, f: F) -> Timeout<F> {
}
}
/// Like [`timeout`], but with an explicit deadline.
#[inline(always)]
pub fn deadline<F: Future>(deadline: Instant, f: F) -> Timeout<F> {
Timeout {
future: f,
deadline: Some(deadline),
}
}
impl<F: Future> Timeout<F> {
#[inline]
fn pin_get_future(self: Pin<&mut Self>) -> Pin<&mut F> {
......@@ -111,10 +120,16 @@ where
/// [`crate::fiber::async`] otherwise the behaviour is undefined.
pub trait IntoTimeout: Future + Sized {
/// Adds timeout to a future. See [`Timeout`].
#[inline]
#[inline(always)]
fn timeout(self, timeout: Duration) -> Timeout<Self> {
self::timeout(timeout, self)
}
/// Adds a deadline to the future. See [`Timeout`].
#[inline(always)]
fn deadline(self, deadline: Instant) -> Timeout<Self> {
self::deadline(deadline, self)
}
}
impl<T> IntoTimeout for T where T: Future + Sized {}
......@@ -215,11 +230,35 @@ mod tests {
DidntYield(Err(Error::Expired))
);
// pending future, deadline is now -> no yield
let (_tx, rx) = oneshot::channel::<i32>();
let now = fiber::clock();
assert_eq!(
check_yield(|| fiber::block_on(deadline(now, rx))),
DidntYield(Err(Error::Expired))
);
// pending future, deadline is past -> no yield
let (_tx, rx) = oneshot::channel::<i32>();
let one_second_ago = now.saturating_sub(Duration::from_secs(1));
assert_eq!(
check_yield(|| fiber::block_on(deadline(one_second_ago, rx))),
DidntYield(Err(Error::Expired))
);
// pending future, positive timeout -> yield
let (_tx, rx) = oneshot::channel::<i32>();
assert_eq!(
check_yield(|| fiber::block_on(timeout(Duration::from_millis(10), rx))),
Yielded(Err(Error::Expired))
);
// pending future, deadline in future -> yield
let (_tx, rx) = oneshot::channel::<i32>();
let in_10_millis = fiber::clock().saturating_add(Duration::from_millis(10));
assert_eq!(
check_yield(|| fiber::block_on(deadline(in_10_millis, rx))),
Yielded(Err(Error::Expired))
);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment