@@ -85,12 +85,11 @@ use std::{
85
85
/// Every non-compatible ABI change will increase this number.
86
86
pub const ABI_VERSION : u32 = 2 ;
87
87
88
- type PollFn < T > = unsafe extern "C" fn ( fut_ptr : * mut ( ) , context_ptr : * mut FfiContext ) -> FfiPoll < T > ;
89
-
90
88
/// The FFI compatible [`std::task::Poll`]
91
89
///
92
90
/// [`std::task::Poll`]: std::task::Poll
93
91
#[ repr( C , u8 ) ]
92
+ #[ cfg_attr( feature = "abi_stable" , derive( abi_stable:: StableAbi ) ) ]
94
93
pub enum FfiPoll < T > {
95
94
/// Represents that a value is immediately ready.
96
95
Ready ( T ) ,
@@ -128,21 +127,22 @@ impl Drop for DropBomb {
128
127
///
129
128
/// [`std::task::Context`]: std::task::Context
130
129
#[ repr( C ) ]
130
+ #[ cfg_attr( feature = "abi_stable" , derive( abi_stable:: StableAbi ) ) ]
131
131
pub struct FfiContext < ' a > {
132
132
/// This waker is passed as borrow semantic.
133
133
/// The external fn must not `drop` or `wake` it.
134
- waker_ref : * const FfiWaker ,
134
+ waker : * const FfiWakerBase ,
135
135
/// Lets the compiler know that this references the FfiWaker and should not outlive it
136
- phantom : PhantomData < & ' a FfiWaker > ,
136
+ _marker : PhantomData < & ' a FfiWakerBase > ,
137
137
}
138
138
139
139
impl < ' a > FfiContext < ' a > {
140
140
/// SAFETY: VTable functions of `waker` are unsafe, the caller must ensure they have a
141
141
/// sane behavior as a Waker. `with_context` relies on this to be safe.
142
142
unsafe fn new ( waker : & ' a FfiWaker ) -> Self {
143
143
Self {
144
- waker_ref : waker as * const _ as * const FfiWaker ,
145
- phantom : PhantomData ,
144
+ waker : waker as * const FfiWaker as * const FfiWakerBase ,
145
+ _marker : PhantomData ,
146
146
}
147
147
}
148
148
@@ -155,30 +155,30 @@ impl<'a> FfiContext<'a> {
155
155
static RUST_WAKER_VTABLE : RawWakerVTable = {
156
156
unsafe fn clone ( data : * const ( ) ) -> RawWaker {
157
157
let waker = data. cast :: < FfiWaker > ( ) ;
158
- let cloned = ( ( * waker) . vtable . clone ) ( waker) ;
158
+ let cloned = ( ( * ( * waker) . base . vtable ) . clone ) ( waker. cast ( ) ) ;
159
159
RawWaker :: new ( cloned. cast ( ) , & RUST_WAKER_VTABLE )
160
160
}
161
161
unsafe fn wake ( data : * const ( ) ) {
162
162
let waker = data. cast :: < FfiWaker > ( ) ;
163
- ( ( * waker) . vtable . wake ) ( waker) ;
163
+ ( ( * ( * waker) . base . vtable ) . wake ) ( waker. cast ( ) ) ;
164
164
}
165
165
unsafe fn wake_by_ref ( data : * const ( ) ) {
166
166
let waker = data. cast :: < FfiWaker > ( ) ;
167
- ( ( * waker) . vtable . wake_by_ref ) ( waker) ;
167
+ ( ( * ( * waker) . base . vtable ) . wake_by_ref ) ( waker. cast ( ) ) ;
168
168
}
169
169
unsafe fn drop ( data : * const ( ) ) {
170
170
let waker = data. cast :: < FfiWaker > ( ) ;
171
- ( ( * waker) . vtable . drop ) ( waker) ;
171
+ ( ( * ( * waker) . base . vtable ) . drop ) ( waker. cast ( ) ) ;
172
172
}
173
173
RawWakerVTable :: new ( clone, wake, wake_by_ref, drop)
174
174
} ;
175
175
176
- // SAFETY: `waker_ref `'s vtable functions must have behavior, this is the contract of
176
+ // SAFETY: `waker `'s vtable functions must have behavior, this is the contract of
177
177
// `FfiContext::new`.
178
178
let waker = unsafe {
179
- // The `waker_ref` is borrowed from external context. We must not call drop on it.
179
+ // The waker reference is borrowed from external context. We must not call drop on it.
180
180
ManuallyDrop :: new ( Waker :: from_raw ( RawWaker :: new (
181
- self . waker_ref . cast ( ) ,
181
+ self . waker . cast ( ) ,
182
182
& RUST_WAKER_VTABLE ,
183
183
) ) )
184
184
} ;
@@ -201,11 +201,14 @@ pub trait ContextExt {
201
201
impl < ' a > ContextExt for Context < ' a > {
202
202
fn with_ffi_context < T , F : FnOnce ( & mut FfiContext ) -> T > ( & mut self , closure : F ) -> T {
203
203
static C_WAKER_VTABLE_OWNED : FfiWakerVTable = {
204
- unsafe extern "C" fn clone ( data : * const FfiWaker ) -> * const FfiWaker {
204
+ unsafe extern "C" fn clone ( data : * const FfiWakerBase ) -> * const FfiWakerBase {
205
205
DropBomb :: with ( "Waker::clone" , || {
206
+ let data = data as * mut FfiWaker ;
206
207
let waker: Waker = ( * ( * data) . waker . owned ) . clone ( ) ;
207
208
Box :: into_raw ( Box :: new ( FfiWaker {
208
- vtable : & C_WAKER_VTABLE_OWNED ,
209
+ base : FfiWakerBase {
210
+ vtable : & C_WAKER_VTABLE_OWNED ,
211
+ } ,
209
212
waker : WakerUnion {
210
213
owned : ManuallyDrop :: new ( waker) ,
211
214
} ,
@@ -215,19 +218,20 @@ impl<'a> ContextExt for Context<'a> {
215
218
}
216
219
// In this case, we must own `data`. This can only happen when the `data` pointer is returned from `clone`.
217
220
// Thus the it is `Box<FfiWaker>`.
218
- unsafe extern "C" fn wake ( data : * const FfiWaker ) {
221
+ unsafe extern "C" fn wake ( data : * const FfiWakerBase ) {
219
222
DropBomb :: with ( "Waker::wake" , || {
220
223
let b = Box :: from_raw ( data as * mut FfiWaker ) ;
221
224
ManuallyDrop :: into_inner ( b. waker . owned ) . wake ( ) ;
222
225
} )
223
226
}
224
- unsafe extern "C" fn wake_by_ref ( data : * const FfiWaker ) {
227
+ unsafe extern "C" fn wake_by_ref ( data : * const FfiWakerBase ) {
225
228
DropBomb :: with ( "Waker::wake_by_ref" , || {
229
+ let data = data as * mut FfiWaker ;
226
230
( * data) . waker . owned . wake_by_ref ( ) ;
227
231
} )
228
232
}
229
233
// Same as `wake`.
230
- unsafe extern "C" fn drop ( data : * const FfiWaker ) {
234
+ unsafe extern "C" fn drop ( data : * const FfiWakerBase ) {
231
235
DropBomb :: with ( "Waker::drop" , || {
232
236
let mut b = Box :: from_raw ( data as * mut FfiWaker ) ;
233
237
ManuallyDrop :: drop ( & mut b. waker . owned ) ;
@@ -243,24 +247,28 @@ impl<'a> ContextExt for Context<'a> {
243
247
} ;
244
248
245
249
static C_WAKER_VTABLE_REF : FfiWakerVTable = {
246
- unsafe extern "C" fn clone ( data : * const FfiWaker ) -> * const FfiWaker {
250
+ unsafe extern "C" fn clone ( data : * const FfiWakerBase ) -> * const FfiWakerBase {
247
251
DropBomb :: with ( "Waker::clone" , || {
252
+ let data = data as * mut FfiWaker ;
248
253
let waker: Waker = ( * ( * data) . waker . reference ) . clone ( ) ;
249
254
Box :: into_raw ( Box :: new ( FfiWaker {
250
- vtable : & C_WAKER_VTABLE_OWNED ,
255
+ base : FfiWakerBase {
256
+ vtable : & C_WAKER_VTABLE_OWNED ,
257
+ } ,
251
258
waker : WakerUnion {
252
259
owned : ManuallyDrop :: new ( waker) ,
253
260
} ,
254
261
} ) )
255
262
. cast ( )
256
263
} )
257
264
}
258
- unsafe extern "C" fn wake_by_ref ( data : * const FfiWaker ) {
265
+ unsafe extern "C" fn wake_by_ref ( data : * const FfiWakerBase ) {
259
266
DropBomb :: with ( "Waker::wake_by_ref" , || {
267
+ let data = data as * mut FfiWaker ;
260
268
( * ( * data) . waker . reference ) . wake_by_ref ( ) ;
261
269
} )
262
270
}
263
- unsafe extern "C" fn unreachable ( _: * const FfiWaker ) {
271
+ unsafe extern "C" fn unreachable ( _: * const FfiWakerBase ) {
264
272
std:: process:: abort ( ) ;
265
273
}
266
274
FfiWakerVTable {
@@ -272,7 +280,9 @@ impl<'a> ContextExt for Context<'a> {
272
280
} ;
273
281
274
282
let waker = FfiWaker {
275
- vtable : & C_WAKER_VTABLE_REF ,
283
+ base : FfiWakerBase {
284
+ vtable : & C_WAKER_VTABLE_REF ,
285
+ } ,
276
286
waker : WakerUnion {
277
287
reference : self . waker ( ) ,
278
288
} ,
@@ -287,9 +297,17 @@ impl<'a> ContextExt for Context<'a> {
287
297
}
288
298
289
299
// Inspired by Gary Guo (github.com/nbdd0121)
300
+ //
301
+ // The base is what can be accessed through FFI, and the regular struct contains
302
+ // internal data (the original waker).
303
+ #[ repr( C ) ]
304
+ #[ cfg_attr( feature = "abi_stable" , derive( abi_stable:: StableAbi ) ) ]
305
+ struct FfiWakerBase {
306
+ vtable : * const FfiWakerVTable ,
307
+ }
290
308
#[ repr( C ) ]
291
309
struct FfiWaker {
292
- vtable : & ' static FfiWakerVTable ,
310
+ base : FfiWakerBase ,
293
311
waker : WakerUnion ,
294
312
}
295
313
@@ -302,17 +320,19 @@ union WakerUnion {
302
320
303
321
#[ derive( PartialEq , Eq , Hash , Clone , Copy ) ]
304
322
#[ repr( C ) ]
323
+ #[ cfg_attr( feature = "abi_stable" , derive( abi_stable:: StableAbi ) ) ]
305
324
struct FfiWakerVTable {
306
- clone : unsafe extern "C" fn ( * const FfiWaker ) -> * const FfiWaker ,
307
- wake : unsafe extern "C" fn ( * const FfiWaker ) ,
308
- wake_by_ref : unsafe extern "C" fn ( * const FfiWaker ) ,
309
- drop : unsafe extern "C" fn ( * const FfiWaker ) ,
325
+ clone : unsafe extern "C" fn ( * const FfiWakerBase ) -> * const FfiWakerBase ,
326
+ wake : unsafe extern "C" fn ( * const FfiWakerBase ) ,
327
+ wake_by_ref : unsafe extern "C" fn ( * const FfiWakerBase ) ,
328
+ drop : unsafe extern "C" fn ( * const FfiWakerBase ) ,
310
329
}
311
330
312
331
/// The FFI compatible future type with `Send` bound.
313
332
///
314
333
/// See [module level documentation](index.html) for more details.
315
334
#[ repr( transparent) ]
335
+ #[ cfg_attr( feature = "abi_stable" , derive( abi_stable:: StableAbi ) ) ]
316
336
pub struct BorrowingFfiFuture < ' a , T > ( LocalBorrowingFfiFuture < ' a , T > ) ;
317
337
318
338
/// The FFI compatible future type with `Send` bound and `'static` lifetime,
@@ -427,9 +447,10 @@ impl<T> Future for BorrowingFfiFuture<'_, T> {
427
447
///
428
448
/// See [module level documentation](index.html) for more details.
429
449
#[ repr( C ) ]
450
+ #[ cfg_attr( feature = "abi_stable" , derive( abi_stable:: StableAbi ) ) ]
430
451
pub struct LocalBorrowingFfiFuture < ' a , T > {
431
452
fut_ptr : * mut ( ) ,
432
- poll_fn : PollFn < T > ,
453
+ poll_fn : unsafe extern "C" fn ( fut_ptr : * mut ( ) , context_ptr : * mut FfiContext ) -> FfiPoll < T > ,
433
454
drop_fn : unsafe extern "C" fn ( * mut ( ) ) ,
434
455
_marker : PhantomData < & ' a ( ) > ,
435
456
}
0 commit comments