1use std::{
2 future::Future,
3 io,
4 task::{Context, Poll},
5 time::Duration,
6};
7
8use crate::context::{io_context, RawIoContext};
9
10use super::{Cmd, Description, Driver, Handle, Interest, OpenFlags};
11
12pub struct Sleep {
14 fd: Option<Handle>,
15 driver: Driver,
16 expired: Duration,
17 poller: Handle,
18}
19
20impl Sleep {
21 pub fn new_with(driver: Driver, poller: Handle, expired: Duration) -> io::Result<Self> {
23 Ok(Self {
24 fd: None,
25 driver,
26 expired,
27 poller,
28 })
29 }
30}
31
32impl Future for Sleep {
33 type Output = io::Result<()>;
34
35 fn poll(mut self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
36 if self.fd.is_none() {
38 let fd = match self
39 .driver
40 .fd_open(Description::Timeout, OpenFlags::Duration(self.expired))
41 {
42 Err(err) => return Poll::Ready(Err(err)),
43 Ok(fd) => fd,
44 };
45
46 self.fd = Some(fd);
47
48 match self.driver.fd_cntl(
49 self.poller,
50 Cmd::Register {
51 source: fd,
52 interests: Interest::Readable,
53 },
54 ) {
55 Err(err) => return Poll::Ready(Err(err)),
56 _ => {}
57 }
58
59 log::trace!("create timeout {:?}", fd);
60 }
61
62 match self
64 .driver
65 .fd_cntl(self.fd.unwrap(), Cmd::Timeout(cx.waker().clone()))
66 {
67 Ok(resp) => match resp.try_into_timeout() {
68 Ok(status) => {
69 if status {
70 return Poll::Ready(Ok(()));
71 }
72 }
73
74 Err(err) => {
75 return Poll::Ready(Err(err));
76 }
77 },
78 Err(err) => return Poll::Ready(Err(err)),
79 }
80
81 return Poll::Pending;
82 }
83}
84
85impl Drop for Sleep {
86 fn drop(&mut self) {
87 if let Some(fd) = self.fd.take() {
88 self.driver.fd_close(fd).unwrap();
89 }
90 }
91}
92
93pub async fn sleep(duration: Duration) -> io::Result<()> {
95 let context = io_context();
96
97 Sleep::new_with(context.driver().clone(), context.poller(), duration)?.await
98}