@@ -83,6 +83,9 @@ impl<'a> LocalExecutor<'a> {
83
83
/// assert!(local_ex.is_empty());
84
84
/// ```
85
85
pub fn is_empty ( & self ) -> bool {
86
+ // SAFETY: All UnsafeCell accesses to active are tightly scoped, and because
87
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
88
+ // values in `State`, including the active field.
86
89
unsafe { & * self . state ( ) . active . get ( ) } . is_empty ( )
87
90
}
88
91
@@ -100,6 +103,9 @@ impl<'a> LocalExecutor<'a> {
100
103
/// });
101
104
/// ```
102
105
pub fn spawn < T : ' a > ( & self , future : impl Future < Output = T > + ' a ) -> Task < T > {
106
+ // SAFETY: All UnsafeCell accesses to active are tightly scoped, and because
107
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
108
+ // values in `State`, including the active field.
103
109
let active = unsafe { & mut * self . state ( ) . active . get ( ) } ;
104
110
self . spawn_inner ( future, active)
105
111
}
@@ -149,6 +155,9 @@ impl<'a> LocalExecutor<'a> {
149
155
futures : impl IntoIterator < Item = F > ,
150
156
handles : & mut impl Extend < Task < F :: Output > > ,
151
157
) {
158
+ // SAFETY: All UnsafeCell accesses to active are tightly scoped, and because
159
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
160
+ // values in `State`, including the active field.
152
161
let active = unsafe { & mut * self . state ( ) . active . get ( ) } ;
153
162
154
163
// Convert the futures into tasks.
@@ -171,6 +180,9 @@ impl<'a> LocalExecutor<'a> {
171
180
let index = entry. key ( ) ;
172
181
let state = self . state_as_rc ( ) ;
173
182
let future = AsyncCallOnDrop :: new ( future, move || {
183
+ // SAFETY: All UnsafeCell accesses to active are tightly scoped, and because
184
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
185
+ // values in `State`, including the active field.
174
186
drop ( unsafe { & mut * state. active . get ( ) } . try_remove ( index) )
175
187
} ) ;
176
188
@@ -276,9 +288,11 @@ impl<'a> LocalExecutor<'a> {
276
288
fn schedule ( & self ) -> impl Fn ( Runnable ) + ' static {
277
289
let state = self . state_as_rc ( ) ;
278
290
279
- // TODO: If possible, push into the current local queue and notify the ticker.
280
291
move |runnable| {
281
292
{
293
+ // SAFETY: All UnsafeCell accesses to queue are tightly scoped, and because
294
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
295
+ // values in `State`, including the queue field.
282
296
let queue = unsafe { & mut * state. queue . get ( ) } ;
283
297
queue. push_front ( runnable) ;
284
298
}
@@ -337,12 +351,18 @@ impl Drop for LocalExecutor<'_> {
337
351
let state = unsafe { Rc :: from_raw ( ptr) } ;
338
352
339
353
{
354
+ // SAFETY: All UnsafeCell accesses to active are tightly scoped, and because
355
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
356
+ // values in `State`, including the active field.
340
357
let active = unsafe { & mut * state. active . get ( ) } ;
341
358
for w in active. drain ( ) {
342
359
w. wake ( ) ;
343
360
}
344
361
}
345
362
363
+ // SAFETY: All UnsafeCell accesses to queue are tightly scoped, and because
364
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
365
+ // values in `State`, including the queue field.
346
366
unsafe { & mut * state. queue . get ( ) } . clear ( ) ;
347
367
}
348
368
}
@@ -382,13 +402,19 @@ impl State {
382
402
/// Notifies a sleeping ticker.
383
403
#[ inline]
384
404
pub ( crate ) fn notify ( & self ) {
405
+ // SAFETY: All UnsafeCell accesses to sleepers are tightly scoped, and because
406
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
407
+ // values in `State`, including the sleepers field.
385
408
let waker = unsafe { & mut * self . sleepers . get ( ) } . notify ( ) ;
386
409
if let Some ( w) = waker {
387
410
w. wake ( ) ;
388
411
}
389
412
}
390
413
391
414
pub ( crate ) fn try_tick ( & self ) -> bool {
415
+ // SAFETY: All UnsafeCell accesses to queue are tightly scoped, and because
416
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
417
+ // values in `State`, including the queue field.
392
418
let runnable = unsafe { & mut * self . queue . get ( ) } . pop_back ( ) ;
393
419
match runnable {
394
420
None => false ,
@@ -449,12 +475,18 @@ impl Ticker<'_> {
449
475
match self . sleeping {
450
476
// Move to sleeping state.
451
477
0 => {
478
+ // SAFETY: All UnsafeCell accesses to sleepers are tightly scoped, and because
479
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
480
+ // values in `State`, including the sleepers field.
452
481
let sleepers = unsafe { & mut * self . state . sleepers . get ( ) } ;
453
482
self . sleeping = sleepers. insert ( waker) ;
454
483
}
455
484
456
485
// Already sleeping, check if notified.
457
486
id => {
487
+ // SAFETY: All UnsafeCell accesses to sleepers are tightly scoped, and because
488
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
489
+ // values in `State`, including the sleepers field.
458
490
let sleepers = unsafe { & mut * self . state . sleepers . get ( ) } ;
459
491
if !sleepers. update ( id, waker) {
460
492
return false ;
@@ -468,6 +500,9 @@ impl Ticker<'_> {
468
500
/// Moves the ticker into woken state.
469
501
fn wake ( & mut self ) {
470
502
if self . sleeping != 0 {
503
+ // SAFETY: All UnsafeCell accesses to sleepers are tightly scoped, and because
504
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
505
+ // values in `State`, including the sleepers field.
471
506
let sleepers = unsafe { & mut * self . state . sleepers . get ( ) } ;
472
507
sleepers. remove ( self . sleeping ) ;
473
508
}
@@ -478,6 +513,9 @@ impl Ticker<'_> {
478
513
async fn runnable ( & mut self ) -> Runnable {
479
514
future:: poll_fn ( |cx| {
480
515
loop {
516
+ // SAFETY: All UnsafeCell accesses to queue are tightly scoped, and because
517
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
518
+ // values in `State`, including the queue field.
481
519
match unsafe { & mut * self . state . queue . get ( ) } . pop_back ( ) {
482
520
None => {
483
521
// Move to sleeping and unnotified state.
@@ -504,6 +542,9 @@ impl Drop for Ticker<'_> {
504
542
// If this ticker is in sleeping state, it must be removed from the sleepers list.
505
543
if self . sleeping != 0 {
506
544
let notified = {
545
+ // SAFETY: All UnsafeCell accesses to sleepers are tightly scoped, and because
546
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
547
+ // values in `State`, including the sleepers field.
507
548
let sleepers = unsafe { & mut * self . state . sleepers . get ( ) } ;
508
549
sleepers. remove ( self . sleeping )
509
550
} ;
@@ -552,6 +593,9 @@ pub(crate) fn debug_state(state: &State, name: &str, f: &mut fmt::Formatter<'_>)
552
593
553
594
impl fmt:: Debug for ActiveTasks < ' _ > {
554
595
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
596
+ // SAFETY: All UnsafeCell accesses to active are tightly scoped, and because
597
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
598
+ // values in `State`, including the active field.
555
599
let active = unsafe { & * self . 0 . get ( ) } ;
556
600
fmt:: Debug :: fmt ( & active. len ( ) , f)
557
601
}
@@ -562,13 +606,19 @@ pub(crate) fn debug_state(state: &State, name: &str, f: &mut fmt::Formatter<'_>)
562
606
563
607
impl fmt:: Debug for SleepCount < ' _ > {
564
608
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
609
+ // SAFETY: All UnsafeCell accesses to sleepers are tightly scoped, and because
610
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
611
+ // values in `State`, including the sleepers field.
565
612
let sleepers = unsafe { & * self . 0 . get ( ) } ;
566
613
fmt:: Debug :: fmt ( & sleepers. count , f)
567
614
}
568
615
}
569
616
570
617
f. debug_struct ( name)
571
618
. field ( "active" , & ActiveTasks ( & state. active ) )
619
+ // SAFETY: All UnsafeCell accesses to queue are tightly scoped, and because
620
+ // `LocalExecutor` is !Send, there is no way to have concurrent access to the
621
+ // values in `State`, including the queue field.
572
622
. field ( "global_tasks" , & unsafe { & * state. queue . get ( ) } . len ( ) )
573
623
. field ( "sleepers" , & SleepCount ( & state. sleepers ) )
574
624
. finish ( )
0 commit comments