|
26 | 26 | //! # Ok(()) }) } |
27 | 27 | //! ``` |
28 | 28 |
|
29 | | -use std::error::Error; |
30 | | -use std::fmt; |
31 | | -use std::pin::Pin; |
32 | | -use std::time::Duration; |
| 29 | +pub use timeout::{Timeout, TimeoutError}; |
33 | 30 |
|
34 | | -use cfg_if::cfg_if; |
35 | | -use futures_timer::Delay; |
36 | | -use pin_utils::unsafe_pinned; |
37 | | - |
38 | | -use crate::future::Future; |
39 | | -use crate::io; |
40 | | -use crate::task::{Context, Poll}; |
41 | | - |
42 | | -cfg_if! { |
43 | | - if #[cfg(feature = "docs")] { |
44 | | - #[doc(hidden)] |
45 | | - pub struct ImplFuture<T>(std::marker::PhantomData<T>); |
46 | | - |
47 | | - macro_rules! ret { |
48 | | - ($f:tt, $o:ty) => (ImplFuture<$o>); |
49 | | - } |
50 | | - } else { |
51 | | - macro_rules! ret { |
52 | | - ($f:tt, $o:ty) => ($f<Self>); |
53 | | - } |
54 | | - } |
55 | | -} |
56 | | - |
57 | | -/// An error returned when a future times out. |
58 | | -#[derive(Clone, Copy, Debug, Eq, PartialEq)] |
59 | | -pub struct TimeoutError; |
60 | | - |
61 | | -impl Error for TimeoutError {} |
62 | | - |
63 | | -impl fmt::Display for TimeoutError { |
64 | | - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
65 | | - "future has timed out".fmt(f) |
66 | | - } |
67 | | -} |
68 | | - |
69 | | -impl From<TimeoutError> for io::Error { |
70 | | - fn from(_: TimeoutError) -> io::Error { |
71 | | - io::Error::new(io::ErrorKind::TimedOut, "future has timed out") |
72 | | - } |
73 | | -} |
74 | | - |
75 | | -/// An extension trait that configures timeouts for futures. |
76 | | -pub trait Timeout: Future + Sized { |
77 | | - /// Awaits a future to completion or times out after a duration of time. |
78 | | - /// |
79 | | - /// # Examples |
80 | | - /// |
81 | | - /// ```no_run |
82 | | - /// # #![feature(async_await)] |
83 | | - /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { |
84 | | - /// # |
85 | | - /// use async_std::{io, prelude::*}; |
86 | | - /// use std::time::Duration; |
87 | | - /// |
88 | | - /// let stdin = io::stdin(); |
89 | | - /// let mut line = String::new(); |
90 | | - /// |
91 | | - /// let n = stdin |
92 | | - /// .read_line(&mut line) |
93 | | - /// .timeout(Duration::from_secs(5)) |
94 | | - /// .await??; |
95 | | - /// # |
96 | | - /// # Ok(()) }) } |
97 | | - /// ``` |
98 | | - fn timeout(self, dur: Duration) -> ret!(TimeoutFuture, Result<Self::Output, TimeoutError>) { |
99 | | - TimeoutFuture { |
100 | | - future: self, |
101 | | - delay: Delay::new(dur), |
102 | | - } |
103 | | - } |
104 | | -} |
105 | | - |
106 | | -/// A future that times out after a duration of time. |
107 | | -#[doc(hidden)] |
108 | | -#[allow(missing_debug_implementations)] |
109 | | -pub struct TimeoutFuture<F> { |
110 | | - future: F, |
111 | | - delay: Delay, |
112 | | -} |
113 | | - |
114 | | -impl<F> TimeoutFuture<F> { |
115 | | - unsafe_pinned!(future: F); |
116 | | - unsafe_pinned!(delay: Delay); |
117 | | -} |
118 | | - |
119 | | -impl<F: Future> Future for TimeoutFuture<F> { |
120 | | - type Output = Result<F::Output, TimeoutError>; |
121 | | - |
122 | | - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
123 | | - match self.as_mut().future().poll(cx) { |
124 | | - Poll::Ready(v) => Poll::Ready(Ok(v)), |
125 | | - Poll::Pending => match self.delay().poll(cx) { |
126 | | - Poll::Ready(_) => Poll::Ready(Err(TimeoutError)), |
127 | | - Poll::Pending => Poll::Pending, |
128 | | - }, |
129 | | - } |
130 | | - } |
131 | | -} |
132 | | - |
133 | | -impl<F: Future> Timeout for F {} |
| 31 | +mod timeout; |
0 commit comments