1
- use std:: { io, marker:: PhantomData , pin:: Pin , task:: Waker } ;
1
+ use std:: { io, marker:: PhantomData , mem :: MaybeUninit , pin:: Pin , task:: Waker } ;
2
2
3
3
use compio_buf:: BufResult ;
4
4
@@ -18,14 +18,45 @@ pub(crate) struct RawOp<T: ?Sized> {
18
18
// strong ref until it completes; the runtime holds the strong ref until the future is
19
19
// dropped.
20
20
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 ,
23
23
result : PushEntry < Option < Waker > , io:: Result < usize > > ,
24
24
op : T ,
25
25
}
26
26
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
29
60
}
30
61
31
62
/// 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> {
38
69
/// by the proactor.
39
70
#[ derive( PartialEq , Eq , Hash ) ]
40
71
pub struct Key < T : ?Sized > {
41
- user_data : usize ,
72
+ user_data : * mut ( ) ,
42
73
_p : PhantomData < Box < T > > ,
43
74
}
44
75
@@ -51,7 +82,7 @@ impl<T: OpCode + 'static> Key<T> {
51
82
let raw_op = Box :: new ( RawOp {
52
83
header,
53
84
cancelled : false ,
54
- upcast_fn : upcast :: < T > ,
85
+ metadata : opcode_metadata :: < T > ( ) ,
55
86
result : PushEntry :: Pending ( None ) ,
56
87
op,
57
88
} ) ;
@@ -69,14 +100,14 @@ impl<T: ?Sized> Key<T> {
69
100
/// `dyn OpCode`.
70
101
pub unsafe fn new_unchecked ( user_data : usize ) -> Self {
71
102
Self {
72
- user_data,
103
+ user_data : user_data as _ ,
73
104
_p : PhantomData ,
74
105
}
75
106
}
76
107
77
108
/// 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 _
80
111
}
81
112
82
113
fn as_opaque ( & self ) -> & RawOp < ( ) > {
@@ -89,6 +120,13 @@ impl<T: ?Sized> Key<T> {
89
120
unsafe { & mut * ( self . user_data as * mut RawOp < ( ) > ) }
90
121
}
91
122
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
+
92
130
/// A pointer to OVERLAPPED.
93
131
#[ cfg( windows) ]
94
132
pub ( crate ) fn as_mut_ptr ( & mut self ) -> * mut Overlapped {
@@ -137,9 +175,7 @@ impl<T: ?Sized> Key<T> {
137
175
/// when the ref count becomes zero. See doc of [`Key::set_cancelled`]
138
176
/// and [`Key::set_result`].
139
177
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 ( ) )
143
179
}
144
180
}
145
181
@@ -160,8 +196,7 @@ impl<T: OpCode + ?Sized> Key<T> {
160
196
pub ( crate ) fn as_op_pin ( & mut self ) -> Pin < & mut dyn OpCode > {
161
197
// SAFETY: the inner won't be moved.
162
198
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 ( ) ;
165
200
Pin :: new_unchecked ( & mut this. op )
166
201
}
167
202
}
@@ -186,6 +221,6 @@ impl<T: OpCode + ?Sized> Key<T> {
186
221
187
222
impl < T : ?Sized > std:: fmt:: Debug for Key < T > {
188
223
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( ) )
190
225
}
191
226
}
0 commit comments