#[macro_use]
extern crate bitflags;
extern crate libc;
use std::fmt::{Debug, Formatter, Result};
use std::io::{self, Error};
use std::os::unix::io::RawFd;
#[repr(i32)]
#[allow(non_camel_case_types)]
pub enum ControlOptions {
EPOLL_CTL_ADD = libc::EPOLL_CTL_ADD,
EPOLL_CTL_MOD = libc::EPOLL_CTL_MOD,
EPOLL_CTL_DEL = libc::EPOLL_CTL_DEL,
}
bitflags! {
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Events: u32 {
const EPOLLET = libc::EPOLLET as u32;
const EPOLLIN = libc::EPOLLIN as u32;
const EPOLLERR = libc::EPOLLERR as u32;
const EPOLLHUP = libc::EPOLLHUP as u32;
const EPOLLOUT = libc::EPOLLOUT as u32;
const EPOLLPRI = libc::EPOLLPRI as u32;
const EPOLLRDHUP = libc::EPOLLRDHUP as u32;
const EPOLLWAKEUP = libc::EPOLLWAKEUP as u32;
const EPOLLONESHOT = libc::EPOLLONESHOT as u32;
const EPOLLEXCLUSIVE = libc::EPOLLEXCLUSIVE as u32;
}
}
#[repr(C)]
#[cfg_attr(target_arch = "x86_64", repr(packed))]
#[derive(Clone, Copy, PartialEq)]
pub struct Event {
pub events: u32,
pub data: u64,
}
impl Event {
pub fn new(events: Events, data: u64) -> Event {
Event {
events: events.bits(),
data: data,
}
}
}
impl Debug for Event {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let data = self.data;
f.debug_struct("Event")
.field("events", &Events::from_bits_retain(self.events)) .field("data", &data)
.finish()
}
}
pub fn create(cloexec: bool) -> io::Result<RawFd> {
let flags = if cloexec { libc::EPOLL_CLOEXEC } else { 0 };
unsafe { cvt(libc::epoll_create1(flags)) }
}
pub fn ctl(
epfd: RawFd,
op: ControlOptions,
fd: RawFd,
mut event: Event,
) -> io::Result<()> {
let e = &mut event as *mut _ as *mut libc::epoll_event;
unsafe { cvt(libc::epoll_ctl(epfd, op as i32, fd, e))? };
Ok(())
}
pub fn wait(epfd: RawFd, timeout: i32, buf: &mut [Event]) -> io::Result<usize> {
let timeout = if timeout < -1 { -1 } else { timeout };
let num_events = unsafe {
cvt(libc::epoll_wait(
epfd,
buf.as_mut_ptr() as *mut libc::epoll_event,
buf.len() as i32,
timeout,
))? as usize
};
Ok(num_events)
}
pub fn close(epfd: RawFd) -> io::Result<()> {
cvt(unsafe { libc::close(epfd) })?;
Ok(())
}
fn cvt(result: libc::c_int) -> io::Result<libc::c_int> {
if result < 0 {
Err(Error::last_os_error())
} else {
Ok(result)
}
}