1
- use std:: cell:: { BorrowError , Cell , RefCell , RefMut } ;
1
+ use std:: cell:: { Cell , UnsafeCell } ;
2
2
use std:: collections:: VecDeque ;
3
3
use std:: fmt;
4
4
use std:: marker:: PhantomData ;
@@ -83,7 +83,7 @@ impl<'a> LocalExecutor<'a> {
83
83
/// assert!(local_ex.is_empty());
84
84
/// ```
85
85
pub fn is_empty ( & self ) -> bool {
86
- self . state ( ) . active ( ) . is_empty ( )
86
+ unsafe { & * self . state ( ) . active . get ( ) } . is_empty ( )
87
87
}
88
88
89
89
/// Spawns a task onto the executor.
@@ -100,8 +100,8 @@ impl<'a> LocalExecutor<'a> {
100
100
/// });
101
101
/// ```
102
102
pub fn spawn < T : ' a > ( & self , future : impl Future < Output = T > + ' a ) -> Task < T > {
103
- let mut active = self . state ( ) . active ( ) ;
104
- self . spawn_inner ( future, & mut active)
103
+ let active = unsafe { & mut * self . state ( ) . active . get ( ) } ;
104
+ self . spawn_inner ( future, active)
105
105
}
106
106
107
107
/// Spawns many tasks onto the executor.
@@ -149,12 +149,12 @@ impl<'a> LocalExecutor<'a> {
149
149
futures : impl IntoIterator < Item = F > ,
150
150
handles : & mut impl Extend < Task < F :: Output > > ,
151
151
) {
152
- let mut active = self . state ( ) . active ( ) ;
152
+ let active = unsafe { & mut * self . state ( ) . active . get ( ) } ;
153
153
154
154
// Convert the futures into tasks.
155
155
let tasks = futures
156
156
. into_iter ( )
157
- . map ( move |future| self . spawn_inner ( future, & mut active) ) ;
157
+ . map ( move |future| self . spawn_inner ( future, active) ) ;
158
158
159
159
// Push the tasks to the user's collection.
160
160
handles. extend ( tasks) ;
@@ -170,7 +170,9 @@ impl<'a> LocalExecutor<'a> {
170
170
let entry = active. vacant_entry ( ) ;
171
171
let index = entry. key ( ) ;
172
172
let state = self . state_as_rc ( ) ;
173
- let future = AsyncCallOnDrop :: new ( future, move || drop ( state. active ( ) . try_remove ( index) ) ) ;
173
+ let future = AsyncCallOnDrop :: new ( future, move || {
174
+ drop ( unsafe { & mut * state. active . get ( ) } . try_remove ( index) )
175
+ } ) ;
174
176
175
177
// Create the task and register it in the set of active tasks.
176
178
//
@@ -276,7 +278,10 @@ impl<'a> LocalExecutor<'a> {
276
278
277
279
// TODO: If possible, push into the current local queue and notify the ticker.
278
280
move |runnable| {
279
- state. queue . borrow_mut ( ) . push_front ( runnable) ;
281
+ {
282
+ let queue = unsafe { & mut * state. queue . get ( ) } ;
283
+ queue. push_front ( runnable) ;
284
+ }
280
285
state. notify ( ) ;
281
286
}
282
287
}
@@ -331,13 +336,14 @@ impl Drop for LocalExecutor<'_> {
331
336
// via Arc::into_raw in state_ptr.
332
337
let state = unsafe { Rc :: from_raw ( ptr) } ;
333
338
334
- let mut active = state. active ( ) ;
335
- for w in active. drain ( ) {
336
- w. wake ( ) ;
339
+ {
340
+ let active = unsafe { & mut * state. active . get ( ) } ;
341
+ for w in active. drain ( ) {
342
+ w. wake ( ) ;
343
+ }
337
344
}
338
- drop ( active) ;
339
345
340
- state. queue . borrow_mut ( ) . clear ( ) ;
346
+ unsafe { & mut * state. queue . get ( ) } . clear ( ) ;
341
347
}
342
348
}
343
349
@@ -350,44 +356,41 @@ impl<'a> Default for LocalExecutor<'a> {
350
356
/// The state of a executor.
351
357
pub ( crate ) struct State {
352
358
/// The global queue.
353
- pub ( crate ) queue : RefCell < VecDeque < Runnable > > ,
359
+ pub ( crate ) queue : UnsafeCell < VecDeque < Runnable > > ,
354
360
355
361
/// A list of sleeping tickers.
356
- sleepers : RefCell < Sleepers > ,
362
+ sleepers : UnsafeCell < Sleepers > ,
357
363
358
364
/// Currently active tasks.
359
- active : RefCell < Slab < Waker > > ,
365
+ pub ( crate ) active : UnsafeCell < Slab < Waker > > ,
360
366
}
361
367
362
368
impl State {
363
369
/// Creates state for a new executor.
364
370
pub ( crate ) const fn new ( ) -> State {
365
371
State {
366
- queue : RefCell :: new ( VecDeque :: new ( ) ) ,
367
- sleepers : RefCell :: new ( Sleepers {
372
+ queue : UnsafeCell :: new ( VecDeque :: new ( ) ) ,
373
+ sleepers : UnsafeCell :: new ( Sleepers {
368
374
count : 0 ,
369
375
wakers : Vec :: new ( ) ,
370
376
free_ids : Vec :: new ( ) ,
371
377
} ) ,
372
- active : RefCell :: new ( Slab :: new ( ) ) ,
378
+ active : UnsafeCell :: new ( Slab :: new ( ) ) ,
373
379
}
374
380
}
375
381
376
- /// Returns a reference to currently active tasks.
377
- pub ( crate ) fn active ( & self ) -> RefMut < ' _ , Slab < Waker > > {
378
- self . active . borrow_mut ( )
379
- }
380
-
381
382
/// Notifies a sleeping ticker.
382
383
#[ inline]
383
384
pub ( crate ) fn notify ( & self ) {
384
- if let Some ( w) = self . sleepers . borrow_mut ( ) . notify ( ) {
385
+ let waker = unsafe { & mut * self . sleepers . get ( ) } . notify ( ) ;
386
+ if let Some ( w) = waker {
385
387
w. wake ( ) ;
386
388
}
387
389
}
388
390
389
391
pub ( crate ) fn try_tick ( & self ) -> bool {
390
- match self . queue . borrow_mut ( ) . pop_back ( ) {
392
+ let runnable = unsafe { & mut * self . queue . get ( ) } . pop_back ( ) ;
393
+ match runnable {
391
394
None => false ,
392
395
Some ( runnable) => {
393
396
// Run the task.
@@ -443,16 +446,16 @@ impl Ticker<'_> {
443
446
///
444
447
/// Returns `false` if the ticker was already sleeping and unnotified.
445
448
fn sleep ( & mut self , waker : & Waker ) -> bool {
446
- let mut sleepers = self . state . sleepers . borrow_mut ( ) ;
447
-
448
449
match self . sleeping {
449
450
// Move to sleeping state.
450
451
0 => {
452
+ let sleepers = unsafe { & mut * self . state . sleepers . get ( ) } ;
451
453
self . sleeping = sleepers. insert ( waker) ;
452
454
}
453
455
454
456
// Already sleeping, check if notified.
455
457
id => {
458
+ let sleepers = unsafe { & mut * self . state . sleepers . get ( ) } ;
456
459
if !sleepers. update ( id, waker) {
457
460
return false ;
458
461
}
@@ -465,7 +468,8 @@ impl Ticker<'_> {
465
468
/// Moves the ticker into woken state.
466
469
fn wake ( & mut self ) {
467
470
if self . sleeping != 0 {
468
- self . state . sleepers . borrow_mut ( ) . remove ( self . sleeping ) ;
471
+ let sleepers = unsafe { & mut * self . state . sleepers . get ( ) } ;
472
+ sleepers. remove ( self . sleeping ) ;
469
473
}
470
474
self . sleeping = 0 ;
471
475
}
@@ -474,7 +478,7 @@ impl Ticker<'_> {
474
478
async fn runnable ( & mut self ) -> Runnable {
475
479
future:: poll_fn ( |cx| {
476
480
loop {
477
- match self . state . queue . borrow_mut ( ) . pop_back ( ) {
481
+ match unsafe { & mut * self . state . queue . get ( ) } . pop_back ( ) {
478
482
None => {
479
483
// Move to sleeping and unnotified state.
480
484
if !self . sleep ( cx. waker ( ) ) {
@@ -499,12 +503,13 @@ impl Drop for Ticker<'_> {
499
503
fn drop ( & mut self ) {
500
504
// If this ticker is in sleeping state, it must be removed from the sleepers list.
501
505
if self . sleeping != 0 {
502
- let mut sleepers = self . state . sleepers . borrow_mut ( ) ;
503
- let notified = sleepers. remove ( self . sleeping ) ;
506
+ let notified = {
507
+ let sleepers = unsafe { & mut * self . state . sleepers . get ( ) } ;
508
+ sleepers. remove ( self . sleeping )
509
+ } ;
504
510
505
511
// If this ticker was notified, then notify another ticker.
506
512
if notified {
507
- drop ( sleepers) ;
508
513
self . state . notify ( ) ;
509
514
}
510
515
}
@@ -543,32 +548,28 @@ fn debug_executor(
543
548
/// Debug implementation for `Executor` and `LocalExecutor`.
544
549
pub ( crate ) fn debug_state ( state : & State , name : & str , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
545
550
/// Debug wrapper for the number of active tasks.
546
- struct ActiveTasks < ' a > ( & ' a RefCell < Slab < Waker > > ) ;
551
+ struct ActiveTasks < ' a > ( & ' a UnsafeCell < Slab < Waker > > ) ;
547
552
548
553
impl fmt:: Debug for ActiveTasks < ' _ > {
549
554
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
550
- match self . 0 . try_borrow ( ) {
551
- Ok ( lock) => fmt:: Debug :: fmt ( & lock. len ( ) , f) ,
552
- Err ( BorrowError { .. } ) => f. write_str ( "<blocked>" ) ,
553
- }
555
+ let active = unsafe { & * self . 0 . get ( ) } ;
556
+ fmt:: Debug :: fmt ( & active. len ( ) , f)
554
557
}
555
558
}
556
559
557
560
/// Debug wrapper for the sleepers.
558
- struct SleepCount < ' a > ( & ' a RefCell < Sleepers > ) ;
561
+ struct SleepCount < ' a > ( & ' a UnsafeCell < Sleepers > ) ;
559
562
560
563
impl fmt:: Debug for SleepCount < ' _ > {
561
564
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
562
- match self . 0 . try_borrow ( ) {
563
- Ok ( sleepers) => fmt:: Debug :: fmt ( & sleepers. count , f) ,
564
- Err ( BorrowError { .. } ) => f. write_str ( "<blocked>" ) ,
565
- }
565
+ let sleepers = unsafe { & * self . 0 . get ( ) } ;
566
+ fmt:: Debug :: fmt ( & sleepers. count , f)
566
567
}
567
568
}
568
569
569
570
f. debug_struct ( name)
570
571
. field ( "active" , & ActiveTasks ( & state. active ) )
571
- . field ( "global_tasks" , & state. queue . borrow ( ) . len ( ) )
572
+ . field ( "global_tasks" , & unsafe { & * state. queue . get ( ) } . len ( ) )
572
573
. field ( "sleepers" , & SleepCount ( & state. sleepers ) )
573
574
. finish ( )
574
575
}
0 commit comments