#![allow(unsafe_code)]
#![allow(unused_qualifications)]
use super::epoll;
#[cfg(feature = "alloc")]
use crate::backend::c;
pub use crate::backend::event::epoll::*;
use crate::backend::event::syscalls;
use crate::fd::{AsFd, OwnedFd};
use crate::io;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::ffi::c_void;
use core::hash::{Hash, Hasher};
use core::slice;
#[inline]
#[doc(alias = "epoll_create1")]
pub fn create(flags: epoll::CreateFlags) -> io::Result<OwnedFd> {
syscalls::epoll_create(flags)
}
#[doc(alias = "epoll_ctl")]
#[inline]
pub fn add(
epoll: impl AsFd,
source: impl AsFd,
data: epoll::EventData,
event_flags: epoll::EventFlags,
) -> io::Result<()> {
syscalls::epoll_add(
epoll.as_fd(),
source.as_fd(),
&Event {
flags: event_flags,
data,
#[cfg(all(libc, target_os = "redox"))]
_pad: 0,
},
)
}
#[doc(alias = "epoll_ctl")]
#[inline]
pub fn modify(
epoll: impl AsFd,
source: impl AsFd,
data: epoll::EventData,
event_flags: epoll::EventFlags,
) -> io::Result<()> {
syscalls::epoll_mod(
epoll.as_fd(),
source.as_fd(),
&Event {
flags: event_flags,
data,
#[cfg(all(libc, target_os = "redox"))]
_pad: 0,
},
)
}
#[doc(alias = "epoll_ctl")]
#[inline]
pub fn delete(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> {
syscalls::epoll_del(epoll.as_fd(), source.as_fd())
}
#[cfg(feature = "alloc")]
#[cfg_attr(docsrs, doc(cfg(feature = "alloc"), alias = "epoll_wait"))]
#[inline]
pub fn wait(epoll: impl AsFd, event_list: &mut EventVec, timeout: c::c_int) -> io::Result<()> {
unsafe {
event_list.events.clear();
let nfds = syscalls::epoll_wait(
epoll.as_fd(),
event_list.events.spare_capacity_mut(),
timeout,
)?;
event_list.events.set_len(nfds);
}
Ok(())
}
pub struct Iter<'a> {
iter: core::iter::Copied<slice::Iter<'a, Event>>,
}
impl<'a> Iterator for Iter<'a> {
type Item = epoll::Event;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
#[repr(C)]
#[cfg_attr(all(not(libc), target_arch = "x86_64"), repr(packed))]
#[cfg_attr(
all(
libc,
linux_kernel,
any(
all(
target_arch = "x86",
not(target_env = "musl"),
not(target_os = "android"),
),
target_arch = "x86_64",
)
),
repr(packed)
)]
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(
all(solarish, any(target_arch = "x86", target_arch = "x86_64")),
repr(packed(4))
)]
pub struct Event {
pub flags: EventFlags,
pub data: EventData,
#[cfg(all(libc, target_os = "redox"))]
_pad: u64,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub union EventData {
as_u64: u64,
sixty_four_bit_pointer: SixtyFourBitPointer,
}
impl EventData {
#[inline]
pub const fn new_u64(value: u64) -> Self {
Self { as_u64: value }
}
#[inline]
pub const fn new_ptr(value: *mut c_void) -> Self {
Self {
sixty_four_bit_pointer: SixtyFourBitPointer {
pointer: value,
#[cfg(target_pointer_width = "32")]
_padding: 0,
},
}
}
#[inline]
pub fn u64(self) -> u64 {
unsafe { self.as_u64 }
}
#[inline]
pub fn ptr(self) -> *mut c_void {
unsafe { self.sixty_four_bit_pointer.pointer }
}
}
impl PartialEq for EventData {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.u64() == other.u64()
}
}
impl Eq for EventData {}
impl Hash for EventData {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.u64().hash(state)
}
}
#[repr(C)]
#[derive(Copy, Clone)]
struct SixtyFourBitPointer {
#[cfg(target_endian = "big")]
#[cfg(target_pointer_width = "32")]
_padding: u32,
pointer: *mut c_void,
#[cfg(target_endian = "little")]
#[cfg(target_pointer_width = "32")]
_padding: u32,
}
#[cfg(feature = "alloc")]
pub struct EventVec {
events: Vec<Event>,
}
#[cfg(feature = "alloc")]
impl EventVec {
#[inline]
pub unsafe fn from_raw_parts(ptr: *mut Event, len: usize, capacity: usize) -> Self {
Self {
events: Vec::from_raw_parts(ptr, len, capacity),
}
}
#[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().copied(),
}
}
#[inline]
pub fn len(&mut self) -> usize {
self.events.len()
}
#[inline]
pub fn is_empty(&mut self) -> bool {
self.events.is_empty()
}
}
#[cfg(feature = "alloc")]
impl<'a> IntoIterator for &'a EventVec {
type IntoIter = Iter<'a>;
type Item = epoll::Event;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_epoll_layouts() {
check_renamed_type!(Event, epoll_event);
check_renamed_struct_renamed_field!(Event, epoll_event, flags, events);
#[cfg(libc)]
check_renamed_struct_renamed_field!(Event, epoll_event, data, u64);
#[cfg(not(libc))]
check_renamed_struct_renamed_field!(Event, epoll_event, data, data);
}
}