Skip to content

Commit 1c81957

Browse files
authored
Deduplicate the "context" set of structures (#466)
* Deduplicate the "context" set of structures
1 parent af0af27 commit 1c81957

File tree

4 files changed

+171
-310
lines changed

4 files changed

+171
-310
lines changed

src/backend/libc/io/epoll.rs

Lines changed: 3 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,12 @@ use crate::io;
6666
use alloc::vec::Vec;
6767
use bitflags::bitflags;
6868
use core::convert::TryInto;
69-
use core::fmt;
7069
use core::marker::PhantomData;
71-
use core::ops::Deref;
7270
use core::ptr::{null, null_mut};
7371

72+
#[doc(inline)]
73+
pub use crate::io::context::*;
74+
7475
bitflags! {
7576
/// `EPOLL_*` for use with [`Epoll::new`].
7677
pub struct CreateFlags: c::c_int {
@@ -113,158 +114,6 @@ bitflags! {
113114
}
114115
}
115116

116-
/// A reference to a `T`.
117-
pub struct Ref<'a, T> {
118-
t: T,
119-
_phantom: PhantomData<&'a T>,
120-
}
121-
122-
impl<'a, T> Ref<'a, T> {
123-
#[inline]
124-
fn new(t: T) -> Self {
125-
Self {
126-
t,
127-
_phantom: PhantomData,
128-
}
129-
}
130-
131-
#[inline]
132-
fn consume(self) -> T {
133-
self.t
134-
}
135-
}
136-
137-
impl<'a, T> Deref for Ref<'a, T> {
138-
type Target = T;
139-
140-
#[inline]
141-
fn deref(&self) -> &T {
142-
&self.t
143-
}
144-
}
145-
146-
impl<'a, T: fmt::Debug> fmt::Debug for Ref<'a, T> {
147-
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
148-
self.t.fmt(fmt)
149-
}
150-
}
151-
152-
/// A trait for data stored within an [`Epoll`] instance.
153-
pub trait Context {
154-
/// The type of an element owned by this context.
155-
type Data;
156-
157-
/// The type of a value used to refer to an element owned by this context.
158-
type Target: AsFd;
159-
160-
/// Assume ownership of `data`, and returning a `Target`.
161-
fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target>;
162-
163-
/// Encode `target` as a `u64`. The only requirement on this value is that
164-
/// it be decodable by `decode`.
165-
fn encode(&self, target: Ref<'_, Self::Target>) -> u64;
166-
167-
/// Decode `raw`, which is a value encoded by `encode`, into a `Target`.
168-
///
169-
/// # Safety
170-
///
171-
/// `raw` must be a `u64` value returned from `encode`, from the same
172-
/// context, and within the context's lifetime.
173-
unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target>;
174-
175-
/// Release ownership of the value referred to by `target` and return it.
176-
fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data;
177-
}
178-
179-
/// A type implementing [`Context`] where the `Data` type is `BorrowedFd<'a>`.
180-
pub struct Borrowing<'a> {
181-
_phantom: PhantomData<BorrowedFd<'a>>,
182-
}
183-
184-
impl<'a> Context for Borrowing<'a> {
185-
type Data = BorrowedFd<'a>;
186-
type Target = BorrowedFd<'a>;
187-
188-
#[inline]
189-
fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> {
190-
Ref::new(data)
191-
}
192-
193-
#[inline]
194-
fn encode(&self, target: Ref<'_, Self::Target>) -> u64 {
195-
target.as_raw_fd() as u64
196-
}
197-
198-
#[inline]
199-
unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> {
200-
Ref::new(BorrowedFd::<'a>::borrow_raw(raw as RawFd))
201-
}
202-
203-
#[inline]
204-
fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data {
205-
target.consume()
206-
}
207-
}
208-
209-
/// A type implementing [`Context`] where the `Data` type is `T`, a type
210-
/// implementing `From<OwnedFd>` and `From<T> for OwnedFd`.
211-
///
212-
/// This may be used with [`OwnedFd`], or higher-level types like
213-
/// [`std::fs::File`] or [`std::net::TcpStream`].
214-
#[cfg(not(feature = "rustc-dep-of-std"))]
215-
pub struct Owning<'context, T: Into<OwnedFd> + From<OwnedFd>> {
216-
_phantom: PhantomData<&'context T>,
217-
}
218-
219-
#[cfg(not(feature = "rustc-dep-of-std"))]
220-
impl<'context, T: Into<OwnedFd> + From<OwnedFd>> Owning<'context, T> {
221-
/// Creates a new empty `Owning`.
222-
#[allow(clippy::new_without_default)] // This is a specialized type that doesn't need to be generically constructible.
223-
#[inline]
224-
pub fn new() -> Self {
225-
Self {
226-
_phantom: PhantomData,
227-
}
228-
}
229-
}
230-
231-
#[cfg(not(feature = "rustc-dep-of-std"))]
232-
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> Context for Owning<'context, T> {
233-
type Data = T;
234-
type Target = BorrowedFd<'context>;
235-
236-
#[inline]
237-
fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> {
238-
let fd: OwnedFd = data.into();
239-
let raw_fd = fd.into_raw_fd();
240-
// Safety: `epoll` will assign ownership of the file descriptor to the
241-
// kernel epoll object. We use `Into<OwnedFd>`+`IntoRawFd` to consume
242-
// the `Data` and extract the raw file descriptor and then "borrow" it
243-
// with `borrow_raw` knowing that the borrow won't outlive the
244-
// kernel epoll object.
245-
unsafe { Ref::new(BorrowedFd::<'context>::borrow_raw(raw_fd)) }
246-
}
247-
248-
#[inline]
249-
fn encode(&self, target: Ref<'_, Self::Target>) -> u64 {
250-
target.as_fd().as_raw_fd() as u64
251-
}
252-
253-
#[inline]
254-
unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> {
255-
Ref::new(BorrowedFd::<'context>::borrow_raw(raw as RawFd))
256-
}
257-
258-
#[inline]
259-
fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data {
260-
// The file descriptor was held by the kernel epoll object and is now
261-
// being released, so we can create a new `OwnedFd` that assumes
262-
// ownership.
263-
let raw_fd = target.consume().as_raw_fd();
264-
unsafe { T::from(OwnedFd::from_raw_fd(raw_fd).into()) }
265-
}
266-
}
267-
268117
/// An "epoll", an interface to an OS object allowing one to repeatedly wait
269118
/// for events from a set of file descriptors efficiently.
270119
pub struct Epoll<Context: self::Context> {

src/backend/linux_raw/io/epoll.rs

Lines changed: 5 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,18 @@
6161

6262
use super::super::c;
6363
use crate::backend::io::syscalls::{epoll_add, epoll_create, epoll_del, epoll_mod, epoll_wait};
64-
use crate::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd};
64+
use crate::fd::{AsFd, AsRawFd, OwnedFd};
6565
#[cfg(feature = "std")]
66-
use crate::fd::{FromRawFd, IntoRawFd};
66+
use crate::fd::{BorrowedFd, FromRawFd, IntoRawFd, RawFd};
6767
use crate::io;
6868
use alloc::vec::Vec;
6969
use bitflags::bitflags;
70-
use core::fmt;
7170
use core::marker::PhantomData;
72-
use core::ops::Deref;
7371
use core::ptr::null;
7472

73+
#[doc(inline)]
74+
pub use crate::io::context::*;
75+
7576
bitflags! {
7677
/// `EPOLL_*` for use with [`Epoll::new`].
7778
pub struct CreateFlags: c::c_uint {
@@ -113,158 +114,6 @@ bitflags! {
113114
}
114115
}
115116

116-
/// A reference to a `T`.
117-
pub struct Ref<'a, T> {
118-
t: T,
119-
_phantom: PhantomData<&'a T>,
120-
}
121-
122-
impl<'a, T> Ref<'a, T> {
123-
#[inline]
124-
fn new(t: T) -> Self {
125-
Self {
126-
t,
127-
_phantom: PhantomData,
128-
}
129-
}
130-
131-
#[inline]
132-
fn consume(self) -> T {
133-
self.t
134-
}
135-
}
136-
137-
impl<'a, T> Deref for Ref<'a, T> {
138-
type Target = T;
139-
140-
#[inline]
141-
fn deref(&self) -> &T {
142-
&self.t
143-
}
144-
}
145-
146-
impl<'a, T: fmt::Debug> fmt::Debug for Ref<'a, T> {
147-
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
148-
self.t.fmt(fmt)
149-
}
150-
}
151-
152-
/// A trait for data stored within an [`Epoll`] instance.
153-
pub trait Context {
154-
/// The type of an element owned by this context.
155-
type Data;
156-
157-
/// The type of a value used to refer to an element owned by this context.
158-
type Target: AsFd;
159-
160-
/// Assume ownership of `data`, and returning a `Target`.
161-
fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target>;
162-
163-
/// Encode `target` as a `u64`. The only requirement on this value is that
164-
/// it be decodable by `decode`.
165-
fn encode(&self, target: Ref<'_, Self::Target>) -> u64;
166-
167-
/// Decode `raw`, which is a value encoded by `encode`, into a `Target`.
168-
///
169-
/// # Safety
170-
///
171-
/// `raw` must be a `u64` value returned from `encode`, from the same
172-
/// context, and within the context's lifetime.
173-
unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target>;
174-
175-
/// Release ownership of the value referred to by `target` and return it.
176-
fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data;
177-
}
178-
179-
/// A type implementing [`Context`] where the `Data` type is `BorrowedFd<'a>`.
180-
pub struct Borrowing<'a> {
181-
_phantom: PhantomData<BorrowedFd<'a>>,
182-
}
183-
184-
impl<'a> Context for Borrowing<'a> {
185-
type Data = BorrowedFd<'a>;
186-
type Target = BorrowedFd<'a>;
187-
188-
#[inline]
189-
fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> {
190-
Ref::new(data)
191-
}
192-
193-
#[inline]
194-
fn encode(&self, target: Ref<'_, Self::Target>) -> u64 {
195-
target.as_raw_fd() as u64
196-
}
197-
198-
#[inline]
199-
unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> {
200-
Ref::new(BorrowedFd::<'a>::borrow_raw(raw as RawFd))
201-
}
202-
203-
#[inline]
204-
fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data {
205-
target.consume()
206-
}
207-
}
208-
209-
/// A type implementing [`Context`] where the `Data` type is `T`, a type
210-
/// implementing `From<OwnedFd>` and `From<T> of OwnedFd`.
211-
///
212-
/// This may be used with [`OwnedFd`], or higher-level types like
213-
/// [`std::fs::File`] or [`std::net::TcpStream`].
214-
#[cfg(feature = "std")]
215-
pub struct Owning<'context, T: Into<OwnedFd> + From<OwnedFd>> {
216-
_phantom: PhantomData<&'context T>,
217-
}
218-
219-
#[cfg(feature = "std")]
220-
impl<'context, T: Into<OwnedFd> + From<OwnedFd>> Owning<'context, T> {
221-
/// Creates a new empty `Owning`.
222-
#[allow(clippy::new_without_default)] // This is a specialized type that doesn't need to be generically constructible.
223-
#[inline]
224-
pub fn new() -> Self {
225-
Self {
226-
_phantom: PhantomData,
227-
}
228-
}
229-
}
230-
231-
#[cfg(feature = "std")]
232-
impl<'context, T: AsFd + Into<OwnedFd> + From<OwnedFd>> Context for Owning<'context, T> {
233-
type Data = T;
234-
type Target = BorrowedFd<'context>;
235-
236-
#[inline]
237-
fn acquire<'call>(&self, data: Self::Data) -> Ref<'call, Self::Target> {
238-
let raw_fd = data.into().into_raw_fd();
239-
// Safety: `epoll` will assign ownership of the file descriptor to the
240-
// kernel epoll object. We use `Into<OwnedFd>`+`IntoRawFd` to consume
241-
// the `Data` and extract the raw file descriptor and then "borrow" it
242-
// with `borrow_raw` knowing that the borrow won't outlive the
243-
// kernel epoll object.
244-
unsafe { Ref::new(BorrowedFd::<'context>::borrow_raw(raw_fd)) }
245-
}
246-
247-
#[inline]
248-
fn encode(&self, target: Ref<'_, Self::Target>) -> u64 {
249-
target.as_fd().as_raw_fd() as u64
250-
}
251-
252-
#[inline]
253-
unsafe fn decode<'call>(&self, raw: u64) -> Ref<'call, Self::Target> {
254-
Ref::new(BorrowedFd::<'context>::borrow_raw(raw as RawFd))
255-
}
256-
257-
#[inline]
258-
fn release(&self, target: Ref<'_, Self::Target>) -> Self::Data {
259-
let raw_fd = target.consume().as_raw_fd();
260-
261-
// Safety: The file descriptor was held by the kernel epoll object and
262-
// is now being released, so we can create a new `OwnedFd` that assumes
263-
// ownership.
264-
unsafe { T::from(io_lifetimes::OwnedFd::from_raw_fd(raw_fd)) }
265-
}
266-
}
267-
268117
/// An "epoll", an interface to an OS object allowing one to repeatedly wait
269118
/// for events from a set of file descriptors efficiently.
270119
pub struct Epoll<Context: self::Context> {

0 commit comments

Comments
 (0)