21
21
#![ forbid( unsafe_code) ]
22
22
#![ warn( missing_docs, missing_debug_implementations, rust_2018_idioms) ]
23
23
24
- use std:: cell:: Cell ;
25
24
use std:: future:: Future ;
26
25
use std:: marker:: PhantomData ;
27
26
use std:: panic:: { RefUnwindSafe , UnwindSafe } ;
28
27
use std:: pin:: Pin ;
29
28
use std:: rc:: Rc ;
30
- use std:: sync:: atomic:: { AtomicBool , Ordering } ;
29
+ use std:: sync:: atomic:: { AtomicBool , Ordering , AtomicU64 , AtomicUsize } ;
31
30
use std:: sync:: { Arc , Mutex , RwLock } ;
32
31
use std:: task:: { Context , Poll , Waker } ;
33
32
@@ -200,7 +199,7 @@ impl State {
200
199
sleepers : Mutex :: new ( Sleepers {
201
200
count : 0 ,
202
201
wakers : Vec :: new ( ) ,
203
- id_gen : 0 ,
202
+ id_gen : 1 ,
204
203
} ) ,
205
204
}
206
205
}
@@ -489,21 +488,21 @@ struct Ticker<'a> {
489
488
/// The executor state.
490
489
state : & ' a State ,
491
490
492
- /// Set to `true` when in sleeping state.
491
+ /// Set to a non-zero sleeper ID when in sleeping state.
493
492
///
494
493
/// States a ticker can be in:
495
494
/// 1) Woken.
496
495
/// 2a) Sleeping and unnotified.
497
496
/// 2b) Sleeping and notified.
498
- sleeping : Cell < Option < u64 > > ,
497
+ sleeping : AtomicU64 ,
499
498
}
500
499
501
500
impl Ticker < ' _ > {
502
501
/// Creates a ticker.
503
502
fn new ( state : & State ) -> Ticker < ' _ > {
504
503
Ticker {
505
504
state,
506
- sleeping : Cell :: new ( None ) ,
505
+ sleeping : AtomicU64 :: new ( 0 ) ,
507
506
}
508
507
}
509
508
@@ -513,12 +512,12 @@ impl Ticker<'_> {
513
512
fn sleep ( & self , waker : & Waker ) -> bool {
514
513
let mut sleepers = self . state . sleepers . lock ( ) . unwrap ( ) ;
515
514
516
- match self . sleeping . get ( ) {
515
+ match self . sleeping . load ( Ordering :: SeqCst ) {
517
516
// Move to sleeping state.
518
- None => self . sleeping . set ( Some ( sleepers. insert ( waker) ) ) ,
517
+ 0 => self . sleeping . store ( sleepers. insert ( waker) , Ordering :: SeqCst ) ,
519
518
520
519
// Already sleeping, check if notified.
521
- Some ( id ) => {
520
+ id => {
522
521
if !sleepers. update ( id, waker) {
523
522
return false ;
524
523
}
@@ -534,7 +533,8 @@ impl Ticker<'_> {
534
533
535
534
/// Moves the ticker into woken state.
536
535
fn wake ( & self ) {
537
- if let Some ( id) = self . sleeping . take ( ) {
536
+ let id = self . sleeping . swap ( 0 , Ordering :: SeqCst ) ;
537
+ if id != 0 {
538
538
let mut sleepers = self . state . sleepers . lock ( ) . unwrap ( ) ;
539
539
sleepers. remove ( id) ;
540
540
@@ -581,7 +581,8 @@ impl Ticker<'_> {
581
581
impl Drop for Ticker < ' _ > {
582
582
fn drop ( & mut self ) {
583
583
// If this ticker is in sleeping state, it must be removed from the sleepers list.
584
- if let Some ( id) = self . sleeping . take ( ) {
584
+ let id = self . sleeping . swap ( 0 , Ordering :: SeqCst ) ;
585
+ if id != 0 {
585
586
let mut sleepers = self . state . sleepers . lock ( ) . unwrap ( ) ;
586
587
let notified = sleepers. remove ( id) ;
587
588
@@ -613,7 +614,7 @@ struct Runner<'a> {
613
614
local : Arc < ConcurrentQueue < Runnable > > ,
614
615
615
616
/// Bumped every time a runnable task is found.
616
- ticks : Cell < usize > ,
617
+ ticks : AtomicUsize ,
617
618
}
618
619
619
620
impl Runner < ' _ > {
@@ -623,7 +624,7 @@ impl Runner<'_> {
623
624
state,
624
625
ticker : Ticker :: new ( state) ,
625
626
local : Arc :: new ( ConcurrentQueue :: bounded ( 512 ) ) ,
626
- ticks : Cell :: new ( 0 ) ,
627
+ ticks : AtomicUsize :: new ( 0 ) ,
627
628
} ;
628
629
state
629
630
. local_queues
@@ -677,8 +678,7 @@ impl Runner<'_> {
677
678
. await ;
678
679
679
680
// Bump the tick counter.
680
- let ticks = self . ticks . get ( ) ;
681
- self . ticks . set ( ticks. wrapping_add ( 1 ) ) ;
681
+ let ticks = self . ticks . fetch_add ( 1 , Ordering :: SeqCst ) ;
682
682
683
683
if ticks % 64 == 0 {
684
684
// Steal tasks from the global queue to ensure fair task scheduling.
0 commit comments