diff --git a/examples/kq.rs b/examples/kq.rs index fa0cbbd1e..261704486 100644 --- a/examples/kq.rs +++ b/examples/kq.rs @@ -7,7 +7,7 @@ fn main() -> std::io::Result<()> { use rustix::{fd::AsRawFd, fs}; let kq = kqueue()?; - let mut out = Vec::with_capacity(10); + let mut buf: Events<10> = Events::new(); #[cfg(feature = "fs")] let dir = fs::openat( @@ -59,10 +59,11 @@ fn main() -> std::io::Result<()> { eprintln!("Run with --features process to enable more!"); #[cfg(not(feature = "fs"))] eprintln!("Run with --features fs to enable more!"); - unsafe { kevent(&kq, &subs, &mut out, None) }?; loop { - while let Some(e) = out.pop() { + let events = unsafe { kevent(&kq, &subs, &mut buf, None) }?; + + for e in events { match e.filter() { #[cfg(feature = "process")] EventFilter::Signal { signal, times } => { @@ -79,7 +80,6 @@ fn main() -> std::io::Result<()> { _ => eprintln!("Unknown event"), } } - unsafe { kevent(&kq, &[], &mut out, None) }?; } } diff --git a/src/event/kqueue.rs b/src/event/kqueue.rs index 0282b628b..de6c2443c 100644 --- a/src/event/kqueue.rs +++ b/src/event/kqueue.rs @@ -10,7 +10,7 @@ use backend::event::syscalls; use alloc::vec::Vec; use core::mem::{zeroed, MaybeUninit}; -use core::slice::from_raw_parts; +use core::ptr::slice_from_raw_parts_mut; use core::time::Duration; /// A `kqueue` event for use with [`kevent`]. @@ -155,6 +155,39 @@ impl Event { } } +impl Default for Event { + fn default() -> Self { + Event { + inner: kevent_t { + ..unsafe { zeroed() } + }, + } + } +} + +/// A buffer for storing [`Event`] values _produced_ by the [`kevent`] function. +pub struct Events { + inner: [Event; N], +} + +impl Events { + /// Returns a new buffer with enough space for `N` events. + /// + /// # Examples + /// + /// ```no_run + /// use rustix::event::kqueue::Events; + /// + /// // Create a buffer that can hold up to 10 events. + /// let events: Events<10> = Events::new(); + /// ``` + pub fn new() -> Events { + Events { + inner: [Event::default(); N], + } + } +} + /// Bottom 24 bits of a u32. #[cfg(any(apple, freebsdlike))] const EVFILT_USER_FLAGS: u32 = 0x00ff_ffff; @@ -421,7 +454,8 @@ pub fn kqueue() -> io::Result { /// [DragonFly BSD]: https://man.dragonflybsd.org/?command=kevent§ion=2 pub unsafe fn kevent<'a, const N: usize>( kqueue: impl AsFd, - changes: &[Event], + changelist: &[Event], + eventlist: &'a mut Events, timeout: Option, ) -> io::Result<&'a [Event]> { let timeout = timeout.map(|timeout| backend::c::timespec { @@ -429,8 +463,14 @@ pub unsafe fn kevent<'a, const N: usize>( tv_nsec: timeout.subsec_nanos() as _, }); - let mut out_slice: [MaybeUninit; N] = unsafe { MaybeUninit::uninit().assume_init() }; + let out_slice = + slice_from_raw_parts_mut(eventlist.inner.as_mut_ptr().cast(), eventlist.inner.len()); - syscalls::kevent(kqueue.as_fd(), changes, &mut out_slice, timeout.as_ref()) - .map(|res| from_raw_parts(out_slice.as_ptr().cast(), res as usize)) + syscalls::kevent( + kqueue.as_fd(), + changelist, + &mut *out_slice, + timeout.as_ref(), + ) + .map(|res| &eventlist.inner[0..(res as usize)]) }