use std::fs::File;
use std::io::{self, Read, Write};
#[cfg(not(target_os = "hermit"))]
use std::os::fd::{AsRawFd, FromRawFd, RawFd};
#[cfg(target_os = "hermit")]
use std::os::hermit::io::{AsRawFd, FromRawFd, RawFd};
use crate::sys::Selector;
use crate::{Interest, Token};
#[derive(Debug)]
pub(crate) struct Waker {
fd: File,
}
impl Waker {
#[allow(dead_code)] pub(crate) fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
let waker = Waker::new_unregistered()?;
selector.register(waker.fd.as_raw_fd(), token, Interest::READABLE)?;
Ok(waker)
}
pub(crate) fn new_unregistered() -> io::Result<Waker> {
#[cfg(not(target_os = "espidf"))]
let flags = libc::EFD_CLOEXEC | libc::EFD_NONBLOCK;
#[cfg(target_os = "espidf")]
let flags = 0;
let fd = syscall!(eventfd(0, flags))?;
let file = unsafe { File::from_raw_fd(fd) };
Ok(Waker { fd: file })
}
#[allow(clippy::unused_io_amount)] pub(crate) fn wake(&self) -> io::Result<()> {
#[cfg(target_os = "illumos")]
self.reset()?;
let buf: [u8; 8] = 1u64.to_ne_bytes();
match (&self.fd).write(&buf) {
Ok(_) => Ok(()),
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
self.reset()?;
self.wake()
}
Err(err) => Err(err),
}
}
#[allow(dead_code)] pub(crate) fn ack_and_reset(&self) {
let _ = self.reset();
}
#[allow(clippy::unused_io_amount)] fn reset(&self) -> io::Result<()> {
let mut buf: [u8; 8] = 0u64.to_ne_bytes();
match (&self.fd).read(&mut buf) {
Ok(_) => Ok(()),
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Ok(()),
Err(err) => Err(err),
}
}
}
impl AsRawFd for Waker {
fn as_raw_fd(&self) -> RawFd {
self.fd.as_raw_fd()
}
}