1use tokio::time::{Instant, Duration, Sleep, sleep};
2use std::{io, pin::Pin, task::{Poll, Context}, future::Future, sync::{Arc, Mutex}};
3
4#[derive(Debug)]
5pub struct VisitorTimeout {
6 last_visit: Arc<Mutex<Instant>>,
7 timeout: Duration,
8 timer: Sleep,
9}
10
11#[derive(Debug, Clone)]
12pub struct Visitor {
13 last_visit: Arc<Mutex<Instant>>,
14}
15
16impl VisitorTimeout {
17 pub fn new(timeout: Duration) -> (VisitorTimeout, Visitor)
18 {
19 let last_visit = Arc::new(Mutex::new(Instant::now()));
20 (VisitorTimeout {
21 last_visit: last_visit.clone(),
22 timeout,
23 timer: sleep(timeout),
24 }, Visitor {
25 last_visit
26 })
27 }
28 pub fn poll_timeout(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
29 loop {
30 if let Poll::Pending = Pin::new(&mut self.timer).poll(cx) {
31 return Poll::Pending;
32 }
33 let elapsed = self.last_visit.lock().unwrap().elapsed();
34 if elapsed > self.timeout {
35 return Poll::Ready(Err(io::ErrorKind::TimedOut.into()))
36 } else {
37 self.timer = sleep(self.timeout - elapsed);
38 }
39 }
40 }
41}
42
43impl Future for VisitorTimeout {
44 type Output = io::Result<()>;
45 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
46 self.poll_timeout(cx)
47 }
48}
49
50impl Visitor {
51 pub fn visit(&self) {
52 *self.last_visit.lock().unwrap() = Instant::now();
53 }
54}
55
56#[derive(Debug)]
57pub struct Timeout {
58 last_visit: Instant,
59 timeout: Duration,
60 timer: Sleep,
61}
62
63impl Timeout {
64 pub fn new(timeout: Duration) -> Timeout
65 {
66 Timeout {
67 last_visit: Instant::now(),
68 timeout,
69 timer: sleep(timeout),
70 }
71 }
72 pub fn visit(&mut self) {
73 self.last_visit = Instant::now();
74 }
75 pub fn poll_timeout(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
76 loop {
77 if let Poll::Pending = Pin::new(&mut self.timer).poll(cx) {
78 return Poll::Pending;
79 }
80 let elapsed = self.last_visit.elapsed();
81 if elapsed > self.timeout {
82 return Poll::Ready(Err(io::ErrorKind::TimedOut.into()))
83 } else {
84 self.timer = sleep(self.timeout - elapsed);
85 }
86 }
87 }
88}
89
90impl Future for Timeout {
91 type Output = io::Result<()>;
92 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
93 self.poll_timeout(cx)
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 #[test]
100 fn it_works() {
101 assert_eq!(2 + 2, 4);
102 }
103}