#![allow(unsafe_code)]
use super::super::c;
use crate::backend::io::syscalls;
use crate::fd::{AsFd, AsRawFd, OwnedFd};
use crate::io;
use alloc::vec::Vec;
use bitflags::bitflags;
use core::slice;
bitflags! {
pub struct CreateFlags: c::c_uint {
const CLOEXEC = linux_raw_sys::general::EPOLL_CLOEXEC;
}
}
bitflags! {
#[derive(Default)]
pub struct EventFlags: u32 {
const IN = linux_raw_sys::general::EPOLLIN as u32;
const OUT = linux_raw_sys::general::EPOLLOUT as u32;
const PRI = linux_raw_sys::general::EPOLLPRI as u32;
const ERR = linux_raw_sys::general::EPOLLERR as u32;
const HUP = linux_raw_sys::general::EPOLLHUP as u32;
const RDNORM = linux_raw_sys::general::EPOLLRDNORM as u32;
const RDBAND = linux_raw_sys::general::EPOLLRDBAND as u32;
const WRNORM = linux_raw_sys::general::EPOLLWRNORM as u32;
const WRBAND = linux_raw_sys::general::EPOLLWRBAND as u32;
const MSG = linux_raw_sys::general::EPOLLMSG as u32;
const RDHUP = linux_raw_sys::general::EPOLLRDHUP as u32;
const ET = linux_raw_sys::general::EPOLLET as u32;
const ONESHOT = linux_raw_sys::general::EPOLLONESHOT as u32;
const WAKEUP = linux_raw_sys::general::EPOLLWAKEUP as u32;
const EXCLUSIVE = linux_raw_sys::general::EPOLLEXCLUSIVE as u32;
}
}
#[inline]
#[doc(alias = "epoll_create1")]
pub fn epoll_create(flags: CreateFlags) -> io::Result<OwnedFd> {
syscalls::epoll_create(flags)
}
#[doc(alias = "epoll_ctl")]
#[inline]
pub fn epoll_add(
epoll: impl AsFd,
source: impl AsFd,
data: u64,
event_flags: EventFlags,
) -> io::Result<()> {
unsafe {
syscalls::epoll_add(
epoll.as_fd(),
source.as_fd().as_raw_fd(),
&linux_raw_sys::general::epoll_event {
events: event_flags.bits(),
data,
},
)
}
}
#[doc(alias = "epoll_ctl")]
#[inline]
pub fn epoll_mod(
epoll: impl AsFd,
source: impl AsFd,
data: u64,
event_flags: EventFlags,
) -> io::Result<()> {
unsafe {
let raw_fd = source.as_fd().as_raw_fd();
syscalls::epoll_mod(
epoll.as_fd(),
raw_fd,
&linux_raw_sys::general::epoll_event {
events: event_flags.bits(),
data,
},
)
}
}
#[doc(alias = "epoll_ctl")]
#[inline]
pub fn epoll_del(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> {
unsafe {
let raw_fd = source.as_fd().as_raw_fd();
syscalls::epoll_del(epoll.as_fd(), raw_fd)
}
}
#[inline]
pub fn epoll_wait(
epoll: impl AsFd,
event_list: &mut EventVec,
timeout: c::c_int,
) -> io::Result<()> {
unsafe {
event_list.events.set_len(0);
let nfds = syscalls::epoll_wait(
epoll.as_fd(),
event_list.events[..].as_mut_ptr().cast(),
event_list.events.capacity(),
timeout,
)?;
event_list.events.set_len(nfds);
}
Ok(())
}
pub struct Iter<'a> {
iter: slice::Iter<'a, Event>,
}
impl<'a> Iterator for Iter<'a> {
type Item = (EventFlags, u64);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter
.next()
.map(|event| (event.event_flags, event.data))
}
}
#[repr(C)]
#[cfg_attr(target_arch = "x86_64", repr(packed))]
struct Event {
event_flags: EventFlags,
data: u64,
}
pub struct EventVec {
events: Vec<Event>,
}
impl EventVec {
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self {
events: Vec::with_capacity(capacity),
}
}
#[inline]
pub fn capacity(&self) -> usize {
self.events.capacity()
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.events.reserve(additional);
}
#[inline]
pub fn reserve_exact(&mut self, additional: usize) {
self.events.reserve_exact(additional);
}
#[inline]
pub fn clear(&mut self) {
self.events.clear();
}
#[inline]
pub fn shrink_to_fit(&mut self) {
self.events.shrink_to_fit();
}
#[inline]
pub fn iter(&self) -> Iter<'_> {
Iter {
iter: self.events.iter(),
}
}
#[inline]
pub fn len(&mut self) -> usize {
self.events.len()
}
#[inline]
pub fn is_empty(&mut self) -> bool {
self.events.is_empty()
}
}
impl<'a> IntoIterator for &'a EventVec {
type IntoIter = Iter<'a>;
type Item = (EventFlags, u64);
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}