@@ -90,7 +90,7 @@ pub use static_executors::*;
90
90
/// ```
91
91
pub struct Executor < ' a > {
92
92
/// The executor state.
93
- state : AtomicPtr < State > ,
93
+ pub ( crate ) state : AtomicPtr < State > ,
94
94
95
95
/// Makes the `'a` lifetime invariant.
96
96
_marker : PhantomData < std:: cell:: UnsafeCell < & ' a ( ) > > ,
@@ -163,10 +163,11 @@ impl<'a> Executor<'a> {
163
163
/// });
164
164
/// ```
165
165
pub fn spawn < T : Send + ' a > ( & self , future : impl Future < Output = T > + Send + ' a ) -> Task < T > {
166
- let mut active = self . state ( ) . active ( ) ;
166
+ let state = self . state ( ) ;
167
+ let mut active = state. active ( ) ;
167
168
168
169
// SAFETY: `T` and the future are `Send`.
169
- unsafe { self . spawn_inner ( future, & mut active) }
170
+ unsafe { Self :: spawn_inner ( state , future, & mut active) }
170
171
}
171
172
172
173
/// Spawns many tasks onto the executor.
@@ -214,12 +215,13 @@ impl<'a> Executor<'a> {
214
215
futures : impl IntoIterator < Item = F > ,
215
216
handles : & mut impl Extend < Task < F :: Output > > ,
216
217
) {
217
- let mut active = Some ( self . state ( ) . active ( ) ) ;
218
+ let state = self . state ( ) ;
219
+ let mut active = Some ( state. as_ref ( ) . active ( ) ) ;
218
220
219
221
// Convert the futures into tasks.
220
222
let tasks = futures. into_iter ( ) . enumerate ( ) . map ( move |( i, future) | {
221
223
// SAFETY: `T` and the future are `Send`.
222
- let task = unsafe { self . spawn_inner ( future, active. as_mut ( ) . unwrap ( ) ) } ;
224
+ let task = unsafe { Self :: spawn_inner ( state , future, active. as_mut ( ) . unwrap ( ) ) } ;
223
225
224
226
// Yield the lock every once in a while to ease contention.
225
227
if i. wrapping_sub ( 1 ) % 500 == 0 {
@@ -240,14 +242,13 @@ impl<'a> Executor<'a> {
240
242
///
241
243
/// If this is an `Executor`, `F` and `T` must be `Send`.
242
244
unsafe fn spawn_inner < T : ' a > (
243
- & self ,
245
+ state : Pin < & ' a State > ,
244
246
future : impl Future < Output = T > + ' a ,
245
247
active : & mut Slab < Waker > ,
246
248
) -> Task < T > {
247
249
// Remove the task from the set of active tasks when the future finishes.
248
250
let entry = active. vacant_entry ( ) ;
249
251
let index = entry. key ( ) ;
250
- let state = self . state_as_arc ( ) ;
251
252
let future = AsyncCallOnDrop :: new ( future, move || drop ( state. active ( ) . try_remove ( index) ) ) ;
252
253
253
254
// Create the task and register it in the set of active tasks.
@@ -269,12 +270,16 @@ impl<'a> Executor<'a> {
269
270
// the `Executor` is drained of all of its runnables. This ensures that
270
271
// runnables are dropped and this precondition is satisfied.
271
272
//
272
- // `self.schedule()` is `Send`, `Sync` and `'static`, as checked below.
273
- // Therefore we do not need to worry about what is done with the
274
- // `Waker`.
273
+ // `Self::schedule` is `Send` and `Sync`, as checked below.
274
+ // Therefore we do not need to worry about which thread the `Waker` is used
275
+ // and dropped on.
276
+ //
277
+ // `Self::schedule` may not be `'static`, but we make sure that the `Waker` does
278
+ // not outlive `'a`. When the executor is dropped, the `active` field is
279
+ // drained and all of the `Waker`s are woken.
275
280
let ( runnable, task) = Builder :: new ( )
276
281
. propagate_panic ( true )
277
- . spawn_unchecked ( |( ) | future, self . schedule ( ) ) ;
282
+ . spawn_unchecked ( |( ) | future, Self :: schedule ( state ) ) ;
278
283
entry. insert ( runnable. waker ( ) ) ;
279
284
280
285
runnable. schedule ( ) ;
@@ -345,9 +350,7 @@ impl<'a> Executor<'a> {
345
350
}
346
351
347
352
/// Returns a function that schedules a runnable task when it gets woken up.
348
- fn schedule ( & self ) -> impl Fn ( Runnable ) + Send + Sync + ' static {
349
- let state = self . state_as_arc ( ) ;
350
-
353
+ fn schedule ( state : Pin < & ' a State > ) -> impl Fn ( Runnable ) + Send + Sync + ' a {
351
354
// TODO: If possible, push into the current local queue and notify the ticker.
352
355
move |runnable| {
353
356
let result = state. queue . push ( runnable) ;
@@ -358,12 +361,11 @@ impl<'a> Executor<'a> {
358
361
359
362
/// Returns a pointer to the inner state.
360
363
#[ inline]
361
- fn state_ptr ( & self ) -> * const State {
364
+ fn state ( & self ) -> Pin < & ' a State > {
362
365
#[ cold]
363
366
fn alloc_state ( atomic_ptr : & AtomicPtr < State > ) -> * mut State {
364
367
let state = Arc :: new ( State :: new ( ) ) ;
365
- // TODO: Switch this to use cast_mut once the MSRV can be bumped past 1.65
366
- let ptr = Arc :: into_raw ( state) as * mut State ;
368
+ let ptr = Arc :: into_raw ( state) . cast_mut ( ) ;
367
369
if let Err ( actual) = atomic_ptr. compare_exchange (
368
370
std:: ptr:: null_mut ( ) ,
369
371
ptr,
@@ -382,26 +384,10 @@ impl<'a> Executor<'a> {
382
384
if ptr. is_null ( ) {
383
385
ptr = alloc_state ( & self . state ) ;
384
386
}
385
- ptr
386
- }
387
387
388
- /// Returns a reference to the inner state.
389
- #[ inline]
390
- fn state ( & self ) -> & State {
391
388
// SAFETY: So long as an Executor lives, it's state pointer will always be valid
392
- // when accessed through state_ptr.
393
- unsafe { & * self . state_ptr ( ) }
394
- }
395
-
396
- // Clones the inner state Arc
397
- #[ inline]
398
- fn state_as_arc ( & self ) -> Arc < State > {
399
- // SAFETY: So long as an Executor lives, it's state pointer will always be a valid
400
- // Arc when accessed through state_ptr.
401
- let arc = unsafe { Arc :: from_raw ( self . state_ptr ( ) ) } ;
402
- let clone = arc. clone ( ) ;
403
- std:: mem:: forget ( arc) ;
404
- clone
389
+ // and will never be moved until it's dropped.
390
+ Pin :: new ( unsafe { & * ptr } )
405
391
}
406
392
}
407
393
@@ -416,7 +402,7 @@ impl Drop for Executor<'_> {
416
402
// via Arc::into_raw in state_ptr.
417
403
let state = unsafe { Arc :: from_raw ( ptr) } ;
418
404
419
- let mut active = state. active ( ) ;
405
+ let mut active = state. pin ( ) . active ( ) ;
420
406
for w in active. drain ( ) {
421
407
w. wake ( ) ;
422
408
}
@@ -518,11 +504,12 @@ impl<'a> LocalExecutor<'a> {
518
504
/// });
519
505
/// ```
520
506
pub fn spawn < T : ' a > ( & self , future : impl Future < Output = T > + ' a ) -> Task < T > {
521
- let mut active = self . inner ( ) . state ( ) . active ( ) ;
507
+ let state = self . inner ( ) . state ( ) ;
508
+ let mut active = state. active ( ) ;
522
509
523
510
// SAFETY: This executor is not thread safe, so the future and its result
524
511
// cannot be sent to another thread.
525
- unsafe { self . inner ( ) . spawn_inner ( future, & mut active) }
512
+ unsafe { Executor :: spawn_inner ( state , future, & mut active) }
526
513
}
527
514
528
515
/// Spawns many tasks onto the executor.
@@ -570,13 +557,14 @@ impl<'a> LocalExecutor<'a> {
570
557
futures : impl IntoIterator < Item = F > ,
571
558
handles : & mut impl Extend < Task < F :: Output > > ,
572
559
) {
573
- let mut active = self . inner ( ) . state ( ) . active ( ) ;
560
+ let state = self . inner ( ) . state ( ) ;
561
+ let mut active = state. active ( ) ;
574
562
575
563
// Convert all of the futures to tasks.
576
564
let tasks = futures. into_iter ( ) . map ( |future| {
577
565
// SAFETY: This executor is not thread safe, so the future and its result
578
566
// cannot be sent to another thread.
579
- unsafe { self . inner ( ) . spawn_inner ( future, & mut active) }
567
+ unsafe { Executor :: spawn_inner ( state , future, & mut active) }
580
568
581
569
// As only one thread can spawn or poll tasks at a time, there is no need
582
570
// to release lock contention here.
@@ -695,9 +683,16 @@ impl State {
695
683
}
696
684
}
697
685
686
+ fn pin ( & self ) -> Pin < & Self > {
687
+ Pin :: new ( self )
688
+ }
689
+
698
690
/// Returns a reference to currently active tasks.
699
- fn active ( & self ) -> MutexGuard < ' _ , Slab < Waker > > {
700
- self . active . lock ( ) . unwrap_or_else ( PoisonError :: into_inner)
691
+ fn active ( self : Pin < & Self > ) -> MutexGuard < ' _ , Slab < Waker > > {
692
+ self . get_ref ( )
693
+ . active
694
+ . lock ( )
695
+ . unwrap_or_else ( PoisonError :: into_inner)
701
696
}
702
697
703
698
/// Notifies a sleeping ticker.
@@ -1209,13 +1204,14 @@ fn _ensure_send_and_sync() {
1209
1204
is_sync :: < Executor < ' _ > > ( Executor :: new ( ) ) ;
1210
1205
1211
1206
let ex = Executor :: new ( ) ;
1207
+ let state = ex. state ( ) ;
1212
1208
is_send ( ex. run ( pending :: < ( ) > ( ) ) ) ;
1213
1209
is_sync ( ex. run ( pending :: < ( ) > ( ) ) ) ;
1214
1210
is_send ( ex. tick ( ) ) ;
1215
1211
is_sync ( ex. tick ( ) ) ;
1216
- is_send ( ex . schedule ( ) ) ;
1217
- is_sync ( ex . schedule ( ) ) ;
1218
- is_static ( ex . schedule ( ) ) ;
1212
+ is_send ( Executor :: schedule ( state ) ) ;
1213
+ is_sync ( Executor :: schedule ( state ) ) ;
1214
+ is_static ( Executor :: schedule ( state ) ) ;
1219
1215
1220
1216
/// ```compile_fail
1221
1217
/// use async_executor::LocalExecutor;
0 commit comments