agnostic_lite/async_io/
sleep.rs1use ::async_io::Timer;
2use core::{
3 future::Future,
4 pin::Pin,
5 task::{Context, Poll},
6 time::Duration,
7};
8
9use std::time::Instant;
10
11use crate::time::{AsyncLocalSleep, AsyncLocalSleepExt};
12
13pin_project_lite::pin_project! {
14 #[derive(Debug)]
16 #[repr(transparent)]
17 #[cfg_attr(docsrs, doc(cfg(feature = "async-io")))]
18 pub struct AsyncIoSleep {
19 #[pin]
20 t: Timer,
21 }
22}
23
24impl From<Timer> for AsyncIoSleep {
25 fn from(t: Timer) -> Self {
26 Self { t }
27 }
28}
29
30impl From<AsyncIoSleep> for Timer {
31 fn from(s: AsyncIoSleep) -> Self {
32 s.t
33 }
34}
35
36impl Future for AsyncIoSleep {
37 type Output = Instant;
38
39 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
40 self.project().t.poll(cx)
41 }
42}
43
44impl AsyncLocalSleepExt for AsyncIoSleep {
45 fn sleep_local(after: Duration) -> Self
46 where
47 Self: Sized,
48 {
49 Self {
50 t: Timer::after(after),
51 }
52 }
53
54 fn sleep_local_until(deadline: Instant) -> Self
55 where
56 Self: Sized,
57 {
58 Self {
59 t: Timer::at(deadline),
60 }
61 }
62}
63
64impl AsyncLocalSleep for AsyncIoSleep {
65 type Instant = Instant;
66
67 fn reset(self: Pin<&mut Self>, deadline: Instant) {
68 self.project().t.as_mut().set_at(deadline)
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::AsyncIoSleep;
75 use crate::time::{AsyncSleep, AsyncSleepExt};
76 use core::pin::Pin;
77 use std::time::{Duration, Instant};
78
79 const ORIGINAL: Duration = Duration::from_secs(1);
80 const RESET: Duration = Duration::from_secs(2);
81 const BOUND: Duration = Duration::from_millis(10);
82
83 #[test]
84 fn test_asyncio_sleep() {
85 futures::executor::block_on(async {
86 let start = Instant::now();
87 let sleep = AsyncIoSleep::sleep(ORIGINAL);
88 let ins = sleep.await;
89 assert!(ins >= start + ORIGINAL);
90 let elapsed = start.elapsed();
91 assert!(elapsed >= ORIGINAL && elapsed < ORIGINAL + BOUND);
92 });
93 }
94
95 #[test]
96 fn test_asyncio_sleep_until() {
97 futures::executor::block_on(async {
98 let start = Instant::now();
99 let sleep = AsyncIoSleep::sleep_until(start + ORIGINAL);
100 let ins = sleep.await;
101 assert!(ins >= start + ORIGINAL);
102 let elapsed = start.elapsed();
103 assert!(elapsed >= ORIGINAL && elapsed < ORIGINAL + BOUND);
104 });
105 }
106
107 #[test]
108 fn test_asyncio_sleep_reset() {
109 futures::executor::block_on(async {
110 let start = Instant::now();
111 let mut sleep = AsyncIoSleep::sleep(ORIGINAL);
112 let pin = Pin::new(&mut sleep);
113 pin.reset(Instant::now() + RESET);
114 let ins = sleep.await;
115 assert!(ins >= start + RESET);
116 let elapsed = start.elapsed();
117 assert!(elapsed >= RESET && elapsed < RESET + BOUND);
118 });
119 }
120
121 #[test]
122 fn test_asyncio_sleep_reset2() {
123 futures::executor::block_on(async {
124 let start = Instant::now();
125 let mut sleep = AsyncIoSleep::sleep_until(start + ORIGINAL);
126 let pin = Pin::new(&mut sleep);
127 pin.reset(Instant::now() + RESET);
128 let ins = sleep.await;
129 assert!(ins >= start + RESET);
130 let elapsed = start.elapsed();
131 assert!(elapsed >= RESET && elapsed < RESET + BOUND);
132 });
133 }
134}