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 /// async_io::block_on(async {
28 /// let res = async { "meow" }
29 /// .delay(Duration::from_millis(100)) // longer delay
30 /// .timeout(Duration::from_millis(50)) // shorter timeout
31 /// .await;
32 /// assert_eq!(res.unwrap_err().kind(), io::ErrorKind::TimedOut); // error
33 ///
34 /// let res = async { "meow" }
35 /// .delay(Duration::from_millis(50)) // shorter delay
36 /// .timeout(Duration::from_millis(100)) // longer timeout
37 /// .await;
38 /// assert_eq!(res.unwrap(), "meow"); // success
39 /// });
40 /// ```
41 fn timeout<D>(self, deadline: D) -> Timeout<Self, D::IntoFuture>
42 where
43 Self: Sized,
44 D: IntoFuture,
45 {
46 Timeout::new(self, deadline.into_future())
47 }
48
49 /// Delay resolving the future until the given deadline.
50 ///
51 /// The underlying future will not be polled until the deadline has expired. In addition
52 /// to using a time source as a deadline, any future can be used as a
53 /// deadline too. When used in combination with a multi-consumer channel,
54 /// this method can be used to synchronize the start of multiple futures and streams.
55 ///
56 /// # Example
57 ///
58 /// ```
59 /// use futures_time::prelude::*;
60 /// use futures_time::time::{Instant, Duration};
61 ///
62 /// async_io::block_on(async {
63 /// let now = Instant::now();
64 /// let delay = Duration::from_millis(100);
65 /// let _ = async { "meow" }.delay(delay).await;
66 /// assert!(now.elapsed() >= *delay);
67 /// });
68 /// ```
69 fn delay<D>(self, deadline: D) -> Delay<Self, D::IntoFuture>
70 where
71 Self: Sized,
72 D: IntoFuture,
73 {
74 Delay::new(self, deadline.into_future())
75 }
76
77 /// Suspend or resume execution of a future.
78 ///
79 /// When this method is called the execution of the future will be put into
80 /// a suspended state until the channel returns `Parker::Unpark` or the
81 /// channel's senders are dropped. The underlying future will not be polled
82 /// while the it is paused.
83 fn park<I>(self, interval: I) -> Park<Self, I::IntoStream>
84 where
85 Self: Sized,
86 I: IntoStream<Item = Parker>,
87 {
88 Park::new(self, interval.into_stream())
89 }
90}
91
92impl<T> FutureExt for T where T: Future {}