@@ -83,6 +83,9 @@ impl<'a> LocalExecutor<'a> {
8383 /// assert!(local_ex.is_empty());
8484 /// ```
8585 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.
8689 unsafe { & * self . state ( ) . active . get ( ) } . is_empty ( )
8790 }
8891
@@ -100,6 +103,9 @@ impl<'a> LocalExecutor<'a> {
100103 /// });
101104 /// ```
102105 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.
103109 let active = unsafe { & mut * self . state ( ) . active . get ( ) } ;
104110 self . spawn_inner ( future, active)
105111 }
@@ -149,6 +155,9 @@ impl<'a> LocalExecutor<'a> {
149155 futures : impl IntoIterator < Item = F > ,
150156 handles : & mut impl Extend < Task < F :: Output > > ,
151157 ) {
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.
152161 let active = unsafe { & mut * self . state ( ) . active . get ( ) } ;
153162
154163 // Convert the futures into tasks.
@@ -171,6 +180,9 @@ impl<'a> LocalExecutor<'a> {
171180 let index = entry. key ( ) ;
172181 let state = self . state_as_rc ( ) ;
173182 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.
174186 drop ( unsafe { & mut * state. active . get ( ) } . try_remove ( index) )
175187 } ) ;
176188
@@ -276,9 +288,11 @@ impl<'a> LocalExecutor<'a> {
276288 fn schedule ( & self ) -> impl Fn ( Runnable ) + ' static {
277289 let state = self . state_as_rc ( ) ;
278290
279- // TODO: If possible, push into the current local queue and notify the ticker.
280291 move |runnable| {
281292 {
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.
282296 let queue = unsafe { & mut * state. queue . get ( ) } ;
283297 queue. push_front ( runnable) ;
284298 }
@@ -337,12 +351,18 @@ impl Drop for LocalExecutor<'_> {
337351 let state = unsafe { Rc :: from_raw ( ptr) } ;
338352
339353 {
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.
340357 let active = unsafe { & mut * state. active . get ( ) } ;
341358 for w in active. drain ( ) {
342359 w. wake ( ) ;
343360 }
344361 }
345362
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.
346366 unsafe { & mut * state. queue . get ( ) } . clear ( ) ;
347367 }
348368}
@@ -382,13 +402,19 @@ impl State {
382402 /// Notifies a sleeping ticker.
383403 #[ inline]
384404 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.
385408 let waker = unsafe { & mut * self . sleepers . get ( ) } . notify ( ) ;
386409 if let Some ( w) = waker {
387410 w. wake ( ) ;
388411 }
389412 }
390413
391414 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.
392418 let runnable = unsafe { & mut * self . queue . get ( ) } . pop_back ( ) ;
393419 match runnable {
394420 None => false ,
@@ -449,12 +475,18 @@ impl Ticker<'_> {
449475 match self . sleeping {
450476 // Move to sleeping state.
451477 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.
452481 let sleepers = unsafe { & mut * self . state . sleepers . get ( ) } ;
453482 self . sleeping = sleepers. insert ( waker) ;
454483 }
455484
456485 // Already sleeping, check if notified.
457486 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.
458490 let sleepers = unsafe { & mut * self . state . sleepers . get ( ) } ;
459491 if !sleepers. update ( id, waker) {
460492 return false ;
@@ -468,6 +500,9 @@ impl Ticker<'_> {
468500 /// Moves the ticker into woken state.
469501 fn wake ( & mut self ) {
470502 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.
471506 let sleepers = unsafe { & mut * self . state . sleepers . get ( ) } ;
472507 sleepers. remove ( self . sleeping ) ;
473508 }
@@ -478,6 +513,9 @@ impl Ticker<'_> {
478513 async fn runnable ( & mut self ) -> Runnable {
479514 future:: poll_fn ( |cx| {
480515 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.
481519 match unsafe { & mut * self . state . queue . get ( ) } . pop_back ( ) {
482520 None => {
483521 // Move to sleeping and unnotified state.
@@ -504,6 +542,9 @@ impl Drop for Ticker<'_> {
504542 // If this ticker is in sleeping state, it must be removed from the sleepers list.
505543 if self . sleeping != 0 {
506544 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.
507548 let sleepers = unsafe { & mut * self . state . sleepers . get ( ) } ;
508549 sleepers. remove ( self . sleeping )
509550 } ;
@@ -552,6 +593,9 @@ pub(crate) fn debug_state(state: &State, name: &str, f: &mut fmt::Formatter<'_>)
552593
553594 impl fmt:: Debug for ActiveTasks < ' _ > {
554595 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.
555599 let active = unsafe { & * self . 0 . get ( ) } ;
556600 fmt:: Debug :: fmt ( & active. len ( ) , f)
557601 }
@@ -562,13 +606,19 @@ pub(crate) fn debug_state(state: &State, name: &str, f: &mut fmt::Formatter<'_>)
562606
563607 impl fmt:: Debug for SleepCount < ' _ > {
564608 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.
565612 let sleepers = unsafe { & * self . 0 . get ( ) } ;
566613 fmt:: Debug :: fmt ( & sleepers. count , f)
567614 }
568615 }
569616
570617 f. debug_struct ( name)
571618 . 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.
572622 . field ( "global_tasks" , & unsafe { & * state. queue . get ( ) } . len ( ) )
573623 . field ( "sleepers" , & SleepCount ( & state. sleepers ) )
574624 . finish ( )
0 commit comments