use rustix::event::{EventfdFlags, eventfd};
use super::*;
use crate::sys::driver::AwakeFlag;
#[derive(Debug)]
pub(super) struct Notifier {
notify: Arc<Notify>,
}
impl Notifier {
pub fn new() -> io::Result<Self> {
let fd = eventfd(0, EventfdFlags::CLOEXEC | EventfdFlags::NONBLOCK)?;
Ok(Self {
notify: Arc::new(Notify::new(fd)),
})
}
pub fn clear(&self) -> io::Result<()> {
const LEN: usize = std::mem::size_of::<u64>();
let mut buffer = [0u8; LEN];
let res = poll_io(|| rustix::io::read(self, &mut buffer))?;
debug_assert!(matches!(res, Poll::Pending | Poll::Ready(LEN)));
Ok(())
}
pub fn set_awake(&self) {
self.notify.set_awake();
}
pub fn reset(&self) -> bool {
self.notify.reset()
}
pub fn waker(&self) -> Waker {
Waker::from(self.notify.clone())
}
}
impl AsFd for Notifier {
fn as_fd(&self) -> BorrowedFd<'_> {
self.notify.fd.as_fd()
}
}
impl AsRawFd for Notifier {
fn as_raw_fd(&self) -> RawFd {
self.notify.fd.as_raw_fd()
}
}
#[derive(Debug)]
pub(super) struct Notify {
fd: OwnedFd,
awake: AwakeFlag,
}
impl Notify {
pub fn new(fd: OwnedFd) -> Self {
Self {
fd,
awake: AwakeFlag::new(),
}
}
pub fn set_awake(&self) {
self.awake.set();
}
pub fn reset(&self) -> bool {
self.awake.reset()
}
}
impl Wake for Notify {
fn wake(self: Arc<Self>) {
self.wake_by_ref();
}
fn wake_by_ref(self: &Arc<Self>) {
if !self.awake.wake() {
rustix::io::write(&self.fd, &u64::to_be_bytes(1)).ok();
}
}
}