#![allow(unsafe_code)]
#![allow(unused_qualifications)]
use super::epoll;
pub use crate::backend::event::epoll::*;
use crate::backend::event::syscalls;
use crate::buffer::Buffer;
use crate::fd::{AsFd, OwnedFd};
use crate::io;
use crate::timespec::Timespec;
use core::ffi::c_void;
use core::hash::{Hash, Hasher};
#[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<EpollFd: AsFd, SourceFd: AsFd>(
epoll: EpollFd,
source: SourceFd,
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<EpollFd: AsFd, SourceFd: AsFd>(
epoll: EpollFd,
source: SourceFd,
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<EpollFd: AsFd, SourceFd: AsFd>(epoll: EpollFd, source: SourceFd) -> io::Result<()> {
syscalls::epoll_del(epoll.as_fd(), source.as_fd())
}
#[doc(alias = "epoll_wait")]
#[inline]
pub fn wait<EpollFd: AsFd, Buf: Buffer<Event>>(
epoll: EpollFd,
mut event_list: Buf,
timeout: Option<&Timespec>,
) -> io::Result<Buf::Output> {
let nfds = unsafe { syscalls::epoll_wait(epoll.as_fd(), event_list.parts_mut(), timeout)? };
unsafe { Ok(event_list.assume_init(nfds)) }
}
#[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)
)]
#[cfg_attr(
all(solarish, any(target_arch = "x86", target_arch = "x86_64")),
repr(packed(4))
)]
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
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(test)]
mod tests {
use super::*;
use crate::backend::c;
#[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);
}
}