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 {}