Skip to content

Commit

Permalink
Add uninitialized epoll event APIs
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Saveau <[email protected]>
  • Loading branch information
SUPERCILEX committed Aug 15, 2024
1 parent 3cb8f68 commit d0b8a06
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 14 deletions.
1 change: 0 additions & 1 deletion src/backend/libc/event/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,6 @@ pub(crate) fn epoll_del(epoll: BorrowedFd<'_>, source: BorrowedFd) -> io::Result
}
}

#[cfg(feature = "alloc")]
#[inline]
#[cfg(any(linux_kernel, target_os = "redox"))]
pub(crate) fn epoll_wait(
Expand Down
1 change: 0 additions & 1 deletion src/backend/linux_raw/event/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ pub(crate) fn epoll_del(epfd: BorrowedFd<'_>, fd: BorrowedFd) -> io::Result<()>
}
}

#[cfg(feature = "alloc")]
#[inline]
pub(crate) fn epoll_wait(
epfd: BorrowedFd<'_>,
Expand Down
80 changes: 68 additions & 12 deletions src/event/epoll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
//! ```
#![allow(unsafe_code)]
#![allow(deprecated)]

use crate::backend::c;
pub use crate::backend::event::epoll::*;
Expand Down Expand Up @@ -190,21 +191,16 @@ pub fn delete(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> {
/// - [Linux]
///
/// [Linux]: https://man7.org/linux/man-pages/man2/epoll_wait.2.html
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
#[inline]
pub fn wait(epoll: impl AsFd, event_list: &mut EventVec, timeout: c::c_int) -> io::Result<()> {
pub fn wait<B: buf::EventBuffer>(
epoll: impl AsFd,
mut events: B,
timeout: c::c_int,
) -> io::Result<B::Out> {
unsafe {
event_list.events.set_len(0);
let nfds = syscalls::epoll_wait(
epoll.as_fd(),
event_list.events.spare_capacity_mut(),
timeout,
)?;
event_list.events.set_len(nfds);
let nfds = syscalls::epoll_wait(epoll.as_fd(), events.convert(), timeout)?;
Ok(events.filled(nfds))
}

Ok(())
}

/// An iterator over the `Event`s in an `EventVec`.
Expand Down Expand Up @@ -337,6 +333,7 @@ struct SixtyFourBitPointer {

/// A vector of `Event`s, plus context for interpreting them.
#[cfg(feature = "alloc")]
#[deprecated(note = "Use an array or vec directly instead.")]
pub struct EventVec {
events: Vec<Event>,
}
Expand Down Expand Up @@ -437,3 +434,62 @@ fn test_epoll_layouts() {
#[cfg(not(libc))]
check_renamed_struct_renamed_field!(Event, epoll_event, data, data);
}

mod buf {
use super::Event;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::mem::MaybeUninit;

pub trait EventBuffer {
type Out;

fn convert(&mut self) -> &mut [MaybeUninit<Event>];

unsafe fn filled(self, count: usize) -> Self::Out;
}

#[cfg(feature = "alloc")]
impl EventBuffer for &mut super::EventVec {
type Out = ();

fn convert(&mut self) -> &mut [MaybeUninit<Event>] {
self.events.clear();
self.events.spare_capacity_mut()
}

unsafe fn filled(self, count: usize) -> Self::Out {
unsafe {
self.events.set_len(count);
}
}
}

#[cfg(feature = "alloc")]
impl EventBuffer for &mut Vec<Event> {
type Out = ();

fn convert(&mut self) -> &mut [MaybeUninit<Event>] {
self.spare_capacity_mut()
}

unsafe fn filled(self, count: usize) -> Self::Out {
unsafe {
self.set_len(count);
}
}
}

impl<'a> EventBuffer for &'a mut [MaybeUninit<Event>] {
type Out = &'a mut [Event];

fn convert(&mut self) -> &mut [MaybeUninit<Event>] {
self
}

unsafe fn filled(self, count: usize) -> Self::Out {
let filled = &mut self[..count];
unsafe { core::mem::transmute::<&mut [MaybeUninit<Event>], &mut [Event]>(filled) }
}
}
}

0 comments on commit d0b8a06

Please sign in to comment.