use std::io::{Error, Result};
use std::os::unix::io::{AsRawFd, RawFd};
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::{Duration, Instant};
use futures_core::ready;
use timerfd::{SetTimeFlags, TimerFd as InnerTimerFd, TimerState};
use tokio::io::unix::AsyncFd;
use tokio::io::{AsyncRead, Interest, ReadBuf};
pub use timerfd::ClockId;
mod delay;
mod interval;
pub use delay::Delay;
pub use interval::Interval;
pub struct TimerFd(AsyncFd<InnerTimerFd>);
impl TimerFd {
pub fn new(clock: ClockId) -> std::io::Result<Self> {
let fd = InnerTimerFd::new_custom(clock, true, true)?;
let inner = AsyncFd::with_interest(fd, Interest::READABLE)?;
Ok(TimerFd(inner))
}
fn set_state(&mut self, state: TimerState, flags: SetTimeFlags) {
(self.0).get_mut().set_state(state, flags);
}
}
fn read_u64(fd: RawFd) -> Result<u64> {
let mut buf = [0u8; 8];
let rv = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut _, 8) };
match rv {
len if len >= 0 => Ok(u64::from_ne_bytes(buf)),
_err => Err(Error::last_os_error()),
}
}
impl AsyncRead for TimerFd {
fn poll_read(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
buf: &mut ReadBuf<'_>,
) -> Poll<Result<()>> {
let inner = self.as_mut();
let fd = inner.0.as_raw_fd();
loop {
let mut guard = ready!(inner.0.poll_read_ready(cx))?;
match guard.try_io(|_| read_u64(fd)) {
Ok(res) => {
let num = res?;
buf.put_slice(&num.to_ne_bytes());
break;
}
Err(_) => continue,
}
}
Poll::Ready(Ok(()))
}
}
pub fn sleep(duration: Duration) -> Delay {
Delay::new(Instant::now() + duration).expect("can't create delay")
}