use libc::eventfd;
use std::fs::File;
use std::io::{Read, Write};
use std::os::fd::IntoRawFd;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::{io, result};
pub use libc::{EFD_CLOEXEC, EFD_NONBLOCK, EFD_SEMAPHORE};
#[derive(Debug)]
pub struct EventFd {
eventfd: File,
}
impl EventFd {
pub fn new(flag: i32) -> result::Result<EventFd, io::Error> {
let ret = unsafe { eventfd(0, flag) };
if ret < 0 {
Err(io::Error::last_os_error())
} else {
Ok(EventFd {
eventfd: unsafe { File::from_raw_fd(ret) },
})
}
}
pub fn write(&self, v: u64) -> result::Result<(), io::Error> {
(&self.eventfd).write_all(v.to_ne_bytes().as_slice())
}
pub fn read(&self) -> result::Result<u64, io::Error> {
let mut buf = [0u8; std::mem::size_of::<u64>()];
(&self.eventfd).read_exact(&mut buf)?;
Ok(u64::from_ne_bytes(buf))
}
pub fn try_clone(&self) -> result::Result<EventFd, io::Error> {
Ok(EventFd {
eventfd: self.eventfd.try_clone()?,
})
}
}
impl AsRawFd for EventFd {
fn as_raw_fd(&self) -> RawFd {
self.eventfd.as_raw_fd()
}
}
impl FromRawFd for EventFd {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
EventFd {
eventfd: File::from_raw_fd(fd),
}
}
}
impl IntoRawFd for EventFd {
fn into_raw_fd(self) -> RawFd {
self.eventfd.into_raw_fd()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new() {
EventFd::new(EFD_NONBLOCK).unwrap();
EventFd::new(0).unwrap();
}
#[test]
fn test_read_write() {
let evt = EventFd::new(EFD_NONBLOCK).unwrap();
evt.write(55).unwrap();
assert_eq!(evt.read().unwrap(), 55);
}
#[test]
fn test_write_overflow() {
let evt = EventFd::new(EFD_NONBLOCK).unwrap();
evt.write(u64::MAX - 1).unwrap();
let err = evt.write(1).unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::WouldBlock);
}
#[test]
fn test_read_nothing() {
let evt = EventFd::new(EFD_NONBLOCK).unwrap();
let err = evt.read().unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::WouldBlock);
}
#[test]
fn test_clone() {
let evt = EventFd::new(EFD_NONBLOCK).unwrap();
let evt_clone = evt.try_clone().unwrap();
evt.write(923).unwrap();
assert_eq!(evt_clone.read().unwrap(), 923);
}
}