Skip to content

Commit 9079159

Browse files
committed
Expand epoll::wait supported buffer types
Signed-off-by: Alex Saveau <[email protected]>
1 parent c700ad7 commit 9079159

File tree

3 files changed

+98
-20
lines changed

3 files changed

+98
-20
lines changed

src/buffer.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@
55
use core::mem::MaybeUninit;
66
use core::slice;
77

8-
/// Split an uninitialized byte slice into initialized and uninitialized parts.
8+
/// Split an uninitialized slice into initialized and uninitialized parts.
99
///
1010
/// # Safety
1111
///
12-
/// At least `init` bytes must be initialized.
12+
/// At least `init` items must be initialized.
1313
#[inline]
14-
pub(super) unsafe fn split_init(
15-
buf: &mut [MaybeUninit<u8>],
14+
pub(super) unsafe fn split_init<T>(
15+
buf: &mut [MaybeUninit<T>],
1616
init: usize,
17-
) -> (&mut [u8], &mut [MaybeUninit<u8>]) {
17+
) -> (&mut [T], &mut [MaybeUninit<T>]) {
1818
let (init, uninit) = buf.split_at_mut(init);
19-
let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<u8>(), init.len());
19+
let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
2020
(init, uninit)
2121
}

src/event/epoll.rs

Lines changed: 90 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
7272
#![allow(unsafe_code)]
7373
#![allow(unused_qualifications)]
74+
#![allow(deprecated)]
7475

7576
use super::epoll;
7677
use crate::backend::c;
@@ -80,6 +81,7 @@ use crate::fd::{AsFd, OwnedFd};
8081
use crate::io;
8182
#[cfg(feature = "alloc")]
8283
use alloc::vec::Vec;
84+
pub use buf::EventBuffer;
8385
use core::ffi::c_void;
8486
use core::hash::{Hash, Hasher};
8587
use core::slice;
@@ -191,20 +193,15 @@ pub fn delete(epoll: impl AsFd, source: impl AsFd) -> io::Result<()> {
191193
#[cfg(feature = "alloc")]
192194
#[cfg_attr(docsrs, doc(cfg(feature = "alloc"), alias = "epoll_wait"))]
193195
#[inline]
194-
pub fn wait(epoll: impl AsFd, event_list: &mut EventVec, timeout: c::c_int) -> io::Result<()> {
195-
// SAFETY: We're calling `epoll_wait` via FFI and we know how it
196-
// behaves.
196+
pub fn wait<B: EventBuffer>(
197+
epoll: impl AsFd,
198+
mut events: B,
199+
timeout: c::c_int,
200+
) -> io::Result<B::Out> {
197201
unsafe {
198-
event_list.events.clear();
199-
let nfds = syscalls::epoll_wait(
200-
epoll.as_fd(),
201-
event_list.events.spare_capacity_mut(),
202-
timeout,
203-
)?;
204-
event_list.events.set_len(nfds);
202+
let nfds = syscalls::epoll_wait(epoll.as_fd(), events.convert(buf::Internal), timeout)?;
203+
Ok(events.filled(nfds, buf::Internal))
205204
}
206-
207-
Ok(())
208205
}
209206

210207
/// An iterator over the `Event`s in an `EventVec`.
@@ -342,6 +339,7 @@ struct SixtyFourBitPointer {
342339

343340
/// A vector of `Event`s, plus context for interpreting them.
344341
#[cfg(feature = "alloc")]
342+
#[deprecated(note = "Use an array or vec directly instead.")]
345343
pub struct EventVec {
346344
events: Vec<Event>,
347345
}
@@ -442,3 +440,83 @@ fn test_epoll_layouts() {
442440
#[cfg(not(libc))]
443441
check_renamed_struct_renamed_field!(Event, epoll_event, data, data);
444442
}
443+
444+
mod buf {
445+
use super::Event;
446+
use crate::buffer::split_init;
447+
#[cfg(feature = "alloc")]
448+
use alloc::vec::Vec;
449+
use core::mem::MaybeUninit;
450+
451+
pub struct Internal;
452+
453+
/// Implementation detail trait to support different return types.
454+
///
455+
/// Check the [`Self::Out`] type for each implementation.
456+
pub trait EventBuffer {
457+
/// The return type of this input.
458+
type Out;
459+
460+
#[doc(hidden)]
461+
fn convert(&mut self, _: Internal) -> &mut [MaybeUninit<Event>];
462+
463+
#[doc(hidden)]
464+
unsafe fn filled(self, count: usize, _: Internal) -> Self::Out;
465+
}
466+
467+
#[cfg(feature = "alloc")]
468+
impl EventBuffer for &mut super::EventVec {
469+
type Out = ();
470+
471+
fn convert(&mut self, _: Internal) -> &mut [MaybeUninit<Event>] {
472+
self.events.clear();
473+
self.events.spare_capacity_mut()
474+
}
475+
476+
unsafe fn filled(self, count: usize, _: Internal) -> Self::Out {
477+
unsafe {
478+
self.events.set_len(count);
479+
}
480+
}
481+
}
482+
483+
#[cfg(feature = "alloc")]
484+
impl EventBuffer for &mut Vec<Event> {
485+
type Out = ();
486+
487+
fn convert(&mut self, _: Internal) -> &mut [MaybeUninit<Event>] {
488+
self.spare_capacity_mut()
489+
}
490+
491+
unsafe fn filled(self, count: usize, _: Internal) -> Self::Out {
492+
unsafe {
493+
self.set_len(count);
494+
}
495+
}
496+
}
497+
498+
impl<'a> EventBuffer for &'a mut [Event] {
499+
type Out = &'a mut [Event];
500+
501+
fn convert(&mut self, _: Internal) -> &mut [MaybeUninit<Event>] {
502+
// SAFETY: we (and the kernel) never uninitialize any values
503+
unsafe { core::mem::transmute::<&mut [Event], &mut [MaybeUninit<Event>]>(self) }
504+
}
505+
506+
unsafe fn filled(self, count: usize, _: Internal) -> Self::Out {
507+
&mut self[..count]
508+
}
509+
}
510+
511+
impl<'a> EventBuffer for &'a mut [MaybeUninit<Event>] {
512+
type Out = &'a mut [Event];
513+
514+
fn convert(&mut self, _: Internal) -> &mut [MaybeUninit<Event>] {
515+
self
516+
}
517+
518+
unsafe fn filled(self, count: usize, _: Internal) -> Self::Out {
519+
unsafe { split_init(self, count) }.0
520+
}
521+
}
522+
}

tests/event/epoll.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ fn server(ready: Arc<(Mutex<u16>, Condvar)>) {
4141
let mut next_data = epoll::EventData::new_u64(2);
4242
let mut targets = HashMap::new();
4343

44-
let mut event_list = epoll::EventVec::with_capacity(4);
44+
let mut event_list = Vec::with_capacity(4);
4545
loop {
4646
epoll::wait(&epoll, &mut event_list, -1).unwrap();
47-
for event in &event_list {
47+
for event in event_list.drain(..) {
4848
let target = event.data;
4949
if target.u64() == 1 {
5050
let conn_sock = accept(&listen_sock).unwrap();

0 commit comments

Comments
 (0)