async_executors/iface/
timer.rs1use
2{
3 std :: { time::Duration, future::Future, task::{ Poll, Context }, pin::Pin } ,
4 futures_core :: { future::BoxFuture } ,
5
6 pin_project::pin_project,
7};
8
9#[ blanket::blanket( derive( Ref, Mut, Rc, Arc, Box ) ) ]
23pub trait Timer
25{
26 #[ must_use = "sleep() returns a future, which does nothing unless awaited" ]
29 fn sleep( &self, dur: Duration ) -> BoxFuture<'static, ()>;
31}
32
33
34
35
36pub trait TimerExt: Timer
45{
46 #[ must_use = "timeout() returns a future, which does nothing unless awaited." ]
58 fn timeout<F: Future>( &self, duration: Duration, future: F ) -> Timeout<F>
60 {
61 let sleep_future = self.sleep( duration );
62
63 Timeout { future, sleep_future }
64 }
65}
66
67
68impl<T: Timer> TimerExt for T {}
69
70
71#[ derive( Copy, Clone, Debug, Eq, PartialEq ) ]
78#[allow(clippy::exhaustive_structs)]
80pub struct TimeoutError;
82
83
84impl std::error::Error for TimeoutError {}
85
86
87impl std::fmt::Display for TimeoutError
88{
89 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
90 {
91 write!( f, "Timeout expired" )
92 }
93}
94
95
96impl From<TimeoutError> for std::io::Error
97{
98 fn from( err: TimeoutError ) -> std::io::Error
99 {
100 std::io::Error::new( std::io::ErrorKind::TimedOut, err )
101 }
102}
103
104
105#[pin_project]
108pub struct Timeout<T>
110{
111 #[pin] future: T,
114
115 sleep_future: BoxFuture<'static, ()>,
118}
119
120
121
122impl<T> Future for Timeout<T>
123
124 where T: Future,
125
126{
127 type Output = Result< T::Output, TimeoutError >;
128
129
130 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>
131 {
132 let this = self.project();
133
134
135 if let Poll::Ready(x) = this.future.poll(cx)
136 {
137 return Poll::Ready(Ok(x));
138 }
139
140
141 match this.sleep_future.as_mut().poll(cx)
142 {
143 Poll::Pending => Poll::Pending ,
144 Poll::Ready(()) => Poll::Ready( Err(TimeoutError) ) ,
145 }
146 }
147}
148
149
150impl<T> std::fmt::Debug for Timeout<T>
151{
152 fn fmt( &self, f: &mut std::fmt::Formatter<'_> ) -> std::fmt::Result
153 {
154 write!( f, "Timeout future" )
155 }
156}
157