Skip to content

Commit 6307f2e

Browse files
committed
feat(driver): save ptr metadata directly in RawOp
1 parent 77b5ef1 commit 6307f2e

File tree

1 file changed

+51
-16
lines changed

1 file changed

+51
-16
lines changed

compio-driver/src/key.rs

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{io, marker::PhantomData, pin::Pin, task::Waker};
1+
use std::{io, marker::PhantomData, mem::MaybeUninit, pin::Pin, task::Waker};
22

33
use compio_buf::BufResult;
44

@@ -18,14 +18,45 @@ pub(crate) struct RawOp<T: ?Sized> {
1818
// strong ref until it completes; the runtime holds the strong ref until the future is
1919
// dropped.
2020
cancelled: bool,
21-
// Imitate vtable. It contains enough information to get the correct vtable of T.
22-
upcast_fn: unsafe fn(usize) -> *mut RawOp<dyn OpCode>,
21+
// The metadata in `*mut RawOp<dyn OpCode>`
22+
metadata: usize,
2323
result: PushEntry<Option<Waker>, io::Result<usize>>,
2424
op: T,
2525
}
2626

27-
unsafe fn upcast<T: OpCode>(user_data: usize) -> *mut RawOp<dyn OpCode> {
28-
user_data as *mut RawOp<T> as *mut RawOp<dyn OpCode>
27+
#[repr(C)]
28+
union OpCodePtrRepr {
29+
ptr: *mut RawOp<dyn OpCode>,
30+
components: OpCodePtrComponents,
31+
}
32+
33+
#[repr(C)]
34+
#[derive(Clone, Copy)]
35+
struct OpCodePtrComponents {
36+
data_pointer: *const (),
37+
metadata: usize,
38+
}
39+
40+
fn opcode_metadata<T: OpCode + 'static>() -> usize {
41+
let mut op = MaybeUninit::<RawOp<T>>::uninit();
42+
// SAFETY: same as `core::ptr::metadata`.
43+
unsafe {
44+
OpCodePtrRepr {
45+
ptr: op.as_mut_ptr(),
46+
}
47+
.components
48+
.metadata
49+
}
50+
}
51+
52+
const unsafe fn opcode_dyn_mut(ptr: *const (), metadata: usize) -> *mut RawOp<dyn OpCode> {
53+
OpCodePtrRepr {
54+
components: OpCodePtrComponents {
55+
data_pointer: ptr,
56+
metadata,
57+
},
58+
}
59+
.ptr
2960
}
3061

3162
/// A typed wrapper for key of Ops submitted into driver. It doesn't free the
@@ -38,7 +69,7 @@ unsafe fn upcast<T: OpCode>(user_data: usize) -> *mut RawOp<dyn OpCode> {
3869
/// by the proactor.
3970
#[derive(PartialEq, Eq, Hash)]
4071
pub struct Key<T: ?Sized> {
41-
user_data: usize,
72+
user_data: *mut (),
4273
_p: PhantomData<Box<T>>,
4374
}
4475

@@ -51,7 +82,7 @@ impl<T: OpCode + 'static> Key<T> {
5182
let raw_op = Box::new(RawOp {
5283
header,
5384
cancelled: false,
54-
upcast_fn: upcast::<T>,
85+
metadata: opcode_metadata::<T>(),
5586
result: PushEntry::Pending(None),
5687
op,
5788
});
@@ -69,14 +100,14 @@ impl<T: ?Sized> Key<T> {
69100
/// `dyn OpCode`.
70101
pub unsafe fn new_unchecked(user_data: usize) -> Self {
71102
Self {
72-
user_data,
103+
user_data: user_data as _,
73104
_p: PhantomData,
74105
}
75106
}
76107

77108
/// Get the unique user-defined data.
78-
pub const fn user_data(&self) -> usize {
79-
self.user_data
109+
pub fn user_data(&self) -> usize {
110+
self.user_data as _
80111
}
81112

82113
fn as_opaque(&self) -> &RawOp<()> {
@@ -89,6 +120,13 @@ impl<T: ?Sized> Key<T> {
89120
unsafe { &mut *(self.user_data as *mut RawOp<()>) }
90121
}
91122

123+
fn as_dyn_mut_ptr(&mut self) -> *mut RawOp<dyn OpCode> {
124+
let user_data = self.user_data;
125+
let this = self.as_opaque_mut();
126+
// SAFETY: metadata from `Key::new`.
127+
unsafe { opcode_dyn_mut(user_data, this.metadata) }
128+
}
129+
92130
/// A pointer to OVERLAPPED.
93131
#[cfg(windows)]
94132
pub(crate) fn as_mut_ptr(&mut self) -> *mut Overlapped {
@@ -137,9 +175,7 @@ impl<T: ?Sized> Key<T> {
137175
/// when the ref count becomes zero. See doc of [`Key::set_cancelled`]
138176
/// and [`Key::set_result`].
139177
pub(crate) unsafe fn into_box(mut self) -> Box<RawOp<dyn OpCode>> {
140-
let this = self.as_opaque_mut();
141-
let ptr = (this.upcast_fn)(self.user_data);
142-
Box::from_raw(ptr)
178+
Box::from_raw(self.as_dyn_mut_ptr())
143179
}
144180
}
145181

@@ -160,8 +196,7 @@ impl<T: OpCode + ?Sized> Key<T> {
160196
pub(crate) fn as_op_pin(&mut self) -> Pin<&mut dyn OpCode> {
161197
// SAFETY: the inner won't be moved.
162198
unsafe {
163-
let this = self.as_opaque_mut();
164-
let this = &mut *((this.upcast_fn)(self.user_data));
199+
let this = &mut *self.as_dyn_mut_ptr();
165200
Pin::new_unchecked(&mut this.op)
166201
}
167202
}
@@ -186,6 +221,6 @@ impl<T: OpCode + ?Sized> Key<T> {
186221

187222
impl<T: ?Sized> std::fmt::Debug for Key<T> {
188223
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
189-
write!(f, "Key({})", self.user_data)
224+
write!(f, "Key({})", self.user_data())
190225
}
191226
}

0 commit comments

Comments
 (0)