wstd/future/
future_ext.rs

1use super::{Delay, Timeout};
2use std::future::{Future, IntoFuture};
3
4/// Extend `Future` with time-based operations.
5pub trait FutureExt: Future {
6    /// Return an error if a future does not complete within a given time span.
7    ///
8    /// Typically timeouts are, as the name implies, based on _time_. However
9    /// this method can time out based on any future. This can be useful in
10    /// combination with channels, as it allows (long-lived) futures to be
11    /// cancelled based on some external event.
12    ///
13    /// When a timeout is returned, the future will be dropped and destructors
14    /// will be run.
15    ///
16    /// # Example
17    ///
18    /// ```no_run
19    /// use wstd::prelude::*;
20    /// use wstd::time::{Instant, Duration};
21    /// use std::io;
22    ///
23    /// #[wstd::main]
24    /// async fn main() {
25    ///     let res = async { "meow" }
26    ///         .delay(Duration::from_millis(100))  // longer delay
27    ///         .timeout(Duration::from_millis(50)) // shorter timeout
28    ///         .await;
29    ///     assert_eq!(res.unwrap_err().kind(), io::ErrorKind::TimedOut); // error
30    ///
31    ///     let res = async { "meow" }
32    ///         .delay(Duration::from_millis(50))    // shorter delay
33    ///         .timeout(Duration::from_millis(100)) // longer timeout
34    ///         .await;
35    ///     assert_eq!(res.unwrap(), "meow"); // success
36    /// }
37    /// ```
38    fn timeout<D>(self, deadline: D) -> Timeout<Self, D::IntoFuture>
39    where
40        Self: Sized,
41        D: IntoFuture,
42    {
43        Timeout::new(self, deadline.into_future())
44    }
45
46    /// Delay resolving the future until the given deadline.
47    ///
48    /// The underlying future will not be polled until the deadline has expired. In addition
49    /// to using a time source as a deadline, any future can be used as a
50    /// deadline too. When used in combination with a multi-consumer channel,
51    /// this method can be used to synchronize the start of multiple futures and streams.
52    ///
53    /// # Example
54    ///
55    /// ```no_run
56    /// use wstd::prelude::*;
57    /// use wstd::time::{Instant, Duration};
58    ///
59    /// #[wstd::main]
60    /// async fn main() {
61    ///     let now = Instant::now();
62    ///     let delay = Duration::from_millis(100);
63    ///     let _ = async { "meow" }.delay(delay).await;
64    ///     assert!(now.elapsed() >= delay);
65    /// }
66    /// ```
67    fn delay<D>(self, deadline: D) -> Delay<Self, D::IntoFuture>
68    where
69        Self: Sized,
70        D: IntoFuture,
71    {
72        Delay::new(self, deadline.into_future())
73    }
74}
75
76impl<T> FutureExt for T where T: Future {}