futures_time/future/future_ext.rs
1use core::future::Future;
2
3use crate::channel::Parker;
4use crate::stream::IntoStream;
5
6use super::{Delay, IntoFuture, Park, Timeout};
7
8/// Extend `Future` with time-based operations.
9pub trait FutureExt: Future {
10 /// Return an error if a future does not complete within a given time span.
11 ///
12 /// Typically timeouts are, as the name implies, based on _time_. However
13 /// this method can time out based on any future. This can be useful in
14 /// combination with channels, as it allows (long-lived) futures to be
15 /// cancelled based on some external event.
16 ///
17 /// When a timeout is returned, the future will be dropped and destructors
18 /// will be run.
19 ///
20 /// # Example
21 ///
22 /// ```
23 /// use futures_time::prelude::*;
24 /// use futures_time::time::{Instant, Duration};
25 /// use std::io;
26 ///
27 /// fn main() {
28 /// async_io::block_on(async {
29 /// let res = async { "meow" }
30 /// .delay(Duration::from_millis(100)) // longer delay
31 /// .timeout(Duration::from_millis(50)) // shorter timeout
32 /// .await;
33 /// assert_eq!(res.unwrap_err().kind(), io::ErrorKind::TimedOut); // error
34 ///
35 /// let res = async { "meow" }
36 /// .delay(Duration::from_millis(50)) // shorter delay
37 /// .timeout(Duration::from_millis(100)) // longer timeout
38 /// .await;
39 /// assert_eq!(res.unwrap(), "meow"); // success
40 /// });
41 /// }
42 /// ```
43 fn timeout<D>(self, deadline: D) -> Timeout<Self, D::IntoFuture>
44 where
45 Self: Sized,
46 D: IntoFuture,
47 {
48 Timeout::new(self, deadline.into_future())
49 }
50
51 /// Delay resolving the future until the given deadline.
52 ///
53 /// The underlying future will not be polled until the deadline has expired. In addition
54 /// to using a time source as a deadline, any future can be used as a
55 /// deadline too. When used in combination with a multi-consumer channel,
56 /// this method can be used to synchronize the start of multiple futures and streams.
57 ///
58 /// # Example
59 ///
60 /// ```
61 /// use futures_time::prelude::*;
62 /// use futures_time::time::{Instant, Duration};
63 ///
64 /// fn main() {
65 /// async_io::block_on(async {
66 /// let now = Instant::now();
67 /// let delay = Duration::from_millis(100);
68 /// let _ = async { "meow" }.delay(delay).await;
69 /// assert!(now.elapsed() >= *delay);
70 /// });
71 /// }
72 /// ```
73 fn delay<D>(self, deadline: D) -> Delay<Self, D::IntoFuture>
74 where
75 Self: Sized,
76 D: IntoFuture,
77 {
78 Delay::new(self, deadline.into_future())
79 }
80
81 /// Suspend or resume execution of a future.
82 ///
83 /// When this method is called the execution of the future will be put into
84 /// a suspended state until the channel returns `Parker::Unpark` or the
85 /// channel's senders are dropped. The underlying future will not be polled
86 /// while the it is paused.
87 fn park<I>(self, interval: I) -> Park<Self, I::IntoStream>
88 where
89 Self: Sized,
90 I: IntoStream<Item = Parker>,
91 {
92 Park::new(self, interval.into_stream())
93 }
94}
95
96impl<T> FutureExt for T where T: Future {}