Skip to content

Commit dffc326

Browse files
committed
Rework epoll API
1 parent 811e5ea commit dffc326

File tree

6 files changed

+112
-347
lines changed

6 files changed

+112
-347
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
target
22
Cargo.lock
3+
/.vscode

src/backend/libc/io/epoll.rs

Lines changed: 54 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
//! accept, bind_v4, listen, socket, AddressFamily, Ipv4Addr, Protocol, SocketAddrV4,
1818
//! SocketType,
1919
//! };
20+
//! use std::collections::HashMap;
2021
//! use std::os::unix::io::AsRawFd;
2122
//!
2223
//! // Create a socket and listen on it.
@@ -26,29 +27,35 @@
2627
//!
2728
//! // Create an epoll object. Using `Owning` here means the epoll object will
2829
//! // take ownership of the file descriptors registered with it.
29-
//! let epoll = Epoll::new(epoll::CreateFlags::CLOEXEC, epoll::Owning::new())?;
30-
//!
31-
//! // Remember the socket raw fd, which we use for comparisons only.
32-
//! let raw_listen_sock = listen_sock.as_fd().as_raw_fd();
30+
//! let epoll = Epoll::new(epoll::CreateFlags::CLOEXEC)?;
3331
//!
3432
//! // Register the socket with the epoll object.
35-
//! epoll.add(listen_sock, epoll::EventFlags::IN)?;
33+
//! epoll.add(&listen_sock, 1, epoll::EventFlags::IN)?;
34+
//!
35+
//! // Keep track of the sockets we've opened.
36+
//! let mut next_id = 2;
37+
//! let mut sockets = HashMap::new();
3638
//!
3739
//! // Process events.
3840
//! let mut event_list = epoll::EventVec::with_capacity(4);
3941
//! loop {
4042
//! epoll.wait(&mut event_list, -1)?;
4143
//! for (_event_flags, target) in &event_list {
42-
//! if target.as_raw_fd() == raw_listen_sock {
44+
//! if target == 1 {
4345
//! // Accept a new connection, set it to non-blocking, and
4446
//! // register to be notified when it's ready to write to.
45-
//! let conn_sock = accept(&*target)?;
47+
//! let conn_sock = accept(&listen_sock)?;
4648
//! ioctl_fionbio(&conn_sock, true)?;
47-
//! epoll.add(conn_sock, epoll::EventFlags::OUT | epoll::EventFlags::ET)?;
49+
//! epoll.add(&conn_sock, next_id, epoll::EventFlags::OUT | epoll::EventFlags::ET)?;
50+
//!
51+
//! // Keep track of the socket.
52+
//! sockets.insert(next_id, conn_sock);
53+
//! next_id += 1;
4854
//! } else {
4955
//! // Write a message to the stream and then unregister it.
50-
//! write(&*target, b"hello\n")?;
51-
//! let _ = epoll.del(target)?;
56+
//! let target = sockets.remove(&target).unwrap();
57+
//! write(&target, b"hello\n")?;
58+
//! let _ = epoll.del(&target)?;
5259
//! }
5360
//! }
5461
//! }
@@ -66,11 +73,7 @@ use crate::io;
6673
use alloc::vec::Vec;
6774
use bitflags::bitflags;
6875
use core::convert::TryInto;
69-
use core::marker::PhantomData;
70-
use core::ptr::{null, null_mut};
71-
72-
#[doc(inline)]
73-
pub use crate::io::context::*;
76+
use core::ptr::null_mut;
7477

7578
bitflags! {
7679
/// `EPOLL_*` for use with [`Epoll::new`].
@@ -116,25 +119,23 @@ bitflags! {
116119

117120
/// An "epoll", an interface to an OS object allowing one to repeatedly wait
118121
/// for events from a set of file descriptors efficiently.
119-
pub struct Epoll<Context: self::Context> {
122+
pub struct Epoll {
120123
epoll_fd: OwnedFd,
121-
context: Context,
122124
}
123125

124-
impl<Context: self::Context> Epoll<Context> {
126+
impl Epoll {
125127
/// `epoll_create1(flags)`—Creates a new `Epoll`.
126128
///
127129
/// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file
128130
/// descriptor from being implicitly passed across `exec` boundaries.
129131
#[inline]
130132
#[doc(alias = "epoll_create1")]
131-
pub fn new(flags: CreateFlags, context: Context) -> io::Result<Self> {
133+
pub fn new(flags: CreateFlags) -> io::Result<Self> {
132134
// Safety: We're calling `epoll_create1` via FFI and we know how it
133135
// behaves.
134136
unsafe {
135137
Ok(Self {
136138
epoll_fd: ret_owned_fd(c::epoll_create1(flags.bits()))?,
137-
context,
138139
})
139140
}
140141
}
@@ -145,27 +146,20 @@ impl<Context: self::Context> Epoll<Context> {
145146
/// This registers interest in any of the events set in `events` occurring
146147
/// on the file descriptor associated with `data`.
147148
#[doc(alias = "epoll_ctl")]
148-
pub fn add(
149-
&self,
150-
data: Context::Data,
151-
event_flags: EventFlags,
152-
) -> io::Result<Ref<'_, Context::Target>> {
149+
pub fn add(&self, source: &impl AsFd, data: u64, event_flags: EventFlags) -> io::Result<()> {
153150
// Safety: We're calling `epoll_ctl` via FFI and we know how it
154151
// behaves.
155152
unsafe {
156-
let target = self.context.acquire(data);
157-
let raw_fd = target.as_fd().as_raw_fd();
158-
let encoded = self.context.encode(target);
153+
let raw_fd = source.as_fd().as_raw_fd();
159154
ret(c::epoll_ctl(
160155
self.epoll_fd.as_fd().as_raw_fd(),
161156
c::EPOLL_CTL_ADD,
162157
raw_fd,
163158
&mut c::epoll_event {
164159
events: event_flags.bits(),
165-
r#u64: encoded,
160+
r#u64: data,
166161
},
167-
))?;
168-
Ok(self.context.decode(encoded))
162+
))
169163
}
170164
}
171165

@@ -174,13 +168,9 @@ impl<Context: self::Context> Epoll<Context> {
174168
///
175169
/// This sets the events of interest with `target` to `events`.
176170
#[doc(alias = "epoll_ctl")]
177-
pub fn mod_(
178-
&self,
179-
target: Ref<'_, Context::Target>,
180-
event_flags: EventFlags,
181-
) -> io::Result<()> {
182-
let raw_fd = target.as_fd().as_raw_fd();
183-
let encoded = self.context.encode(target);
171+
pub fn mod_(&self, source: &impl AsFd, data: u64, event_flags: EventFlags) -> io::Result<()> {
172+
let raw_fd = source.as_fd().as_raw_fd();
173+
184174
// Safety: We're calling `epoll_ctl` via FFI and we know how it
185175
// behaves.
186176
unsafe {
@@ -190,7 +180,7 @@ impl<Context: self::Context> Epoll<Context> {
190180
raw_fd,
191181
&mut c::epoll_event {
192182
events: event_flags.bits(),
193-
r#u64: encoded,
183+
r#u64: data,
194184
},
195185
))
196186
}
@@ -201,19 +191,18 @@ impl<Context: self::Context> Epoll<Context> {
201191
///
202192
/// This also returns the owning `Data`.
203193
#[doc(alias = "epoll_ctl")]
204-
pub fn del(&self, target: Ref<'_, Context::Target>) -> io::Result<Context::Data> {
194+
pub fn del(&self, source: &impl AsFd) -> io::Result<()> {
205195
// Safety: We're calling `epoll_ctl` via FFI and we know how it
206196
// behaves.
207197
unsafe {
208-
let raw_fd = target.as_fd().as_raw_fd();
198+
let raw_fd = source.as_fd().as_raw_fd();
209199
ret(c::epoll_ctl(
210200
self.epoll_fd.as_fd().as_raw_fd(),
211201
c::EPOLL_CTL_DEL,
212202
raw_fd,
213203
null_mut(),
214-
))?;
204+
))
215205
}
216-
Ok(self.context.release(target))
217206
}
218207

219208
/// `epoll_wait(self, events, timeout)`—Waits for registered events of
@@ -222,11 +211,7 @@ impl<Context: self::Context> Epoll<Context> {
222211
/// For each event of interest, an element is written to `events`. On
223212
/// success, this returns the number of written elements.
224213
#[doc(alias = "epoll_wait")]
225-
pub fn wait<'context>(
226-
&'context self,
227-
event_list: &mut EventVec<'context, Context>,
228-
timeout: c::c_int,
229-
) -> io::Result<()> {
214+
pub fn wait(&self, event_list: &mut EventVec, timeout: c::c_int) -> io::Result<()> {
230215
// Safety: We're calling `epoll_wait` via FFI and we know how it
231216
// behaves.
232217
unsafe {
@@ -238,84 +223,71 @@ impl<Context: self::Context> Epoll<Context> {
238223
timeout,
239224
))?;
240225
event_list.events.set_len(nfds as usize);
241-
event_list.context = &self.context;
242226
}
243227

244228
Ok(())
245229
}
246230
}
247231

248232
#[cfg(not(feature = "rustc-dep-of-std"))]
249-
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> AsRawFd for Epoll<Owning<'context, T>> {
233+
impl AsRawFd for Epoll {
250234
fn as_raw_fd(&self) -> RawFd {
251235
self.epoll_fd.as_raw_fd()
252236
}
253237
}
254238

255239
#[cfg(not(feature = "rustc-dep-of-std"))]
256-
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> IntoRawFd for Epoll<Owning<'context, T>> {
240+
impl IntoRawFd for Epoll {
257241
fn into_raw_fd(self) -> RawFd {
258242
self.epoll_fd.into_raw_fd()
259243
}
260244
}
261245

262246
#[cfg(not(feature = "rustc-dep-of-std"))]
263-
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> FromRawFd for Epoll<Owning<'context, T>> {
247+
impl FromRawFd for Epoll {
264248
unsafe fn from_raw_fd(fd: RawFd) -> Self {
265249
Self {
266250
epoll_fd: OwnedFd::from_raw_fd(fd),
267-
context: Owning::new(),
268251
}
269252
}
270253
}
271254

272255
#[cfg(not(feature = "rustc-dep-of-std"))]
273-
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> AsFd for Epoll<Owning<'context, T>> {
256+
impl AsFd for Epoll {
274257
fn as_fd(&self) -> BorrowedFd<'_> {
275258
self.epoll_fd.as_fd()
276259
}
277260
}
278261

279262
#[cfg(not(feature = "rustc-dep-of-std"))]
280-
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> From<Epoll<Owning<'context, T>>>
281-
for OwnedFd
282-
{
283-
fn from(epoll: Epoll<Owning<'context, T>>) -> Self {
263+
impl From<Epoll> for OwnedFd {
264+
fn from(epoll: Epoll) -> Self {
284265
epoll.epoll_fd
285266
}
286267
}
287268

288269
#[cfg(not(feature = "rustc-dep-of-std"))]
289-
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> From<OwnedFd>
290-
for Epoll<Owning<'context, T>>
291-
{
270+
impl From<OwnedFd> for Epoll {
292271
fn from(fd: OwnedFd) -> Self {
293-
Self {
294-
epoll_fd: fd,
295-
context: Owning::new(),
296-
}
272+
Self { epoll_fd: fd }
297273
}
298274
}
299275

300276
/// An iterator over the `Event`s in an `EventVec`.
301-
pub struct Iter<'context, Context: self::Context> {
302-
iter: core::slice::Iter<'context, Event>,
303-
context: *const Context,
304-
_phantom: PhantomData<&'context Context>,
277+
pub struct Iter<'a> {
278+
iter: core::slice::Iter<'a, Event>,
305279
}
306280

307-
impl<'context, Context: self::Context> Iterator for Iter<'context, Context> {
308-
type Item = (EventFlags, Ref<'context, Context::Target>);
281+
impl<'a> Iterator for Iter<'a> {
282+
type Item = (EventFlags, u64);
309283

310284
fn next(&mut self) -> Option<Self::Item> {
311285
// Safety: `self.context` is guaranteed to be valid because we hold
312286
// `'context` for it. And we know this event is associated with this
313287
// context because `wait` sets both.
314-
self.iter.next().map(|event| {
315-
(event.event_flags, unsafe {
316-
(*self.context).decode(event.encoded)
317-
})
318-
})
288+
self.iter
289+
.next()
290+
.map(|event| (event.event_flags, event.encoded))
319291
}
320292
}
321293

@@ -341,20 +313,16 @@ struct Event {
341313
}
342314

343315
/// A vector of `Event`s, plus context for interpreting them.
344-
pub struct EventVec<'context, Context: self::Context> {
316+
pub struct EventVec {
345317
events: Vec<Event>,
346-
context: *const Context,
347-
_phantom: PhantomData<&'context Context>,
348318
}
349319

350-
impl<'context, Context: self::Context> EventVec<'context, Context> {
320+
impl EventVec {
351321
/// Constructs an `EventVec` with memory for `capacity` `Event`s.
352322
#[inline]
353323
pub fn with_capacity(capacity: usize) -> Self {
354324
Self {
355325
events: Vec::with_capacity(capacity),
356-
context: null(),
357-
_phantom: PhantomData,
358326
}
359327
}
360328

@@ -390,11 +358,9 @@ impl<'context, Context: self::Context> EventVec<'context, Context> {
390358

391359
/// Returns an iterator over the `Event`s in this `EventVec`.
392360
#[inline]
393-
pub fn iter(&self) -> Iter<'_, Context> {
361+
pub fn iter(&self) -> Iter<'_> {
394362
Iter {
395363
iter: self.events.iter(),
396-
context: self.context,
397-
_phantom: PhantomData,
398364
}
399365
}
400366

@@ -411,9 +377,9 @@ impl<'context, Context: self::Context> EventVec<'context, Context> {
411377
}
412378
}
413379

414-
impl<'context, Context: self::Context> IntoIterator for &'context EventVec<'context, Context> {
415-
type IntoIter = Iter<'context, Context>;
416-
type Item = (EventFlags, Ref<'context, Context::Target>);
380+
impl<'a> IntoIterator for &'a EventVec {
381+
type IntoIter = Iter<'a>;
382+
type Item = (EventFlags, u64);
417383

418384
#[inline]
419385
fn into_iter(self) -> Self::IntoIter {

0 commit comments

Comments
 (0)