use std::{
io,
os::fd::{AsRawFd, FromRawFd, OwnedFd, RawFd},
};
use compio_buf::{arrayvec::ArrayVec, BufResult};
use compio_driver::{impl_raw_fd, op::Recv, syscall};
use crate::{attacher::Attacher, Runtime};
#[derive(Debug)]
pub struct Event {
fd: OwnedFd,
attacher: Attacher,
}
impl Event {
pub fn new() -> io::Result<Self> {
let fd = syscall!(libc::eventfd(0, libc::EFD_CLOEXEC))?;
let fd = unsafe { OwnedFd::from_raw_fd(fd) };
Ok(Self {
fd,
attacher: Attacher::new(),
})
}
pub fn handle(&self) -> io::Result<EventHandle> {
Ok(EventHandle::new(self.fd.try_clone()?))
}
pub async fn wait(self) -> io::Result<()> {
self.attacher.attach(&self.fd)?;
let buffer = ArrayVec::<u8, 8>::new();
let op = Recv::new(self.as_raw_fd(), buffer);
let BufResult(res, _) = Runtime::current().submit(op).await;
res?;
Ok(())
}
}
impl AsRawFd for Event {
fn as_raw_fd(&self) -> RawFd {
self.fd.as_raw_fd()
}
}
pub struct EventHandle {
fd: OwnedFd,
}
impl EventHandle {
pub(crate) fn new(fd: OwnedFd) -> Self {
Self { fd }
}
pub fn notify(self) -> io::Result<()> {
let data = 1u64;
syscall!(libc::write(
self.fd.as_raw_fd(),
&data as *const _ as *const _,
std::mem::size_of::<u64>(),
))?;
Ok(())
}
}
impl_raw_fd!(EventHandle, fd);