use std::os::fd::RawFd;
use std::time::Duration;
pub(crate) struct Waker {
read: RawFd,
write: RawFd,
}
impl Waker {
pub(crate) fn new() -> Result<Self, std::io::Error> {
let mut fds = [0 as libc::c_int; 2];
let rc = unsafe { libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC | libc::O_NONBLOCK) };
if rc != 0 {
return Err(std::io::Error::last_os_error());
}
Ok(Self {
read: fds[0],
write: fds[1],
})
}
pub(crate) fn read_fd(&self) -> RawFd {
self.read
}
pub(crate) fn wake(&self) {
let byte = 1u8;
unsafe {
libc::write(self.write, std::ptr::from_ref(&byte).cast(), 1);
}
}
}
impl Drop for Waker {
fn drop(&mut self) {
unsafe {
libc::close(self.read);
libc::close(self.write);
}
}
}
pub(crate) fn wait_readable(x_fd: RawFd, wake_fd: RawFd, timeout: Option<Duration>) {
let mut fds = [
libc::pollfd {
fd: x_fd,
events: libc::POLLIN,
revents: 0,
},
libc::pollfd {
fd: wake_fd,
events: libc::POLLIN,
revents: 0,
},
];
let millis = timeout.map_or(-1, |d| d.as_millis().min(i32::MAX as u128) as libc::c_int);
unsafe {
libc::poll(fds.as_mut_ptr(), 2, millis);
}
if fds[1].revents & libc::POLLIN != 0 {
let mut buf = [0u8; 64];
while unsafe { libc::read(wake_fd, buf.as_mut_ptr().cast(), buf.len()) } > 0 {}
}
}