@@ -59,8 +59,10 @@ use crate::loom::sync::atomic::AtomicU64;
5959use crate :: loom:: sync:: atomic:: Ordering ;
6060
6161use crate :: runtime:: scheduler;
62+ use crate :: runtime:: time;
6263use crate :: sync:: AtomicWaker ;
6364use crate :: time:: Instant ;
65+ use crate :: util:: error:: { RUNTIME_SHUTTING_DOWN_ERROR , TIME_DISABLED_ERROR } ;
6466use crate :: util:: linked_list;
6567
6668use pin_project_lite:: pin_project;
@@ -285,9 +287,6 @@ pin_project! {
285287 // before polling.
286288 #[ derive( Debug ) ]
287289 pub ( crate ) struct TimerEntry {
288- // Arc reference to the runtime handle. We can only free the driver after
289- // deregistering everything from their respective timer wheels.
290- driver: scheduler:: Handle ,
291290 // Shared inner structure; this is part of an intrusive linked list, and
292291 // therefore other references can exist to it while mutable references to
293292 // Entry exist.
@@ -340,6 +339,10 @@ pub(crate) struct TimerShared {
340339 /// Only accessed under the entry lock.
341340 pointers : linked_list:: Pointers < TimerShared > ,
342341
342+ // Arc reference to the runtime handle. We can only free the driver after
343+ // deregistering everything from their respective timer wheels.
344+ driver : scheduler:: Handle ,
345+
343346 /// The time when the [`TimerEntry`] was registered into the Wheel,
344347 /// [`STATE_DEREGISTERED`] means it is not registered.
345348 ///
@@ -384,11 +387,19 @@ generate_addr_of_methods! {
384387
385388impl TimerShared {
386389 pub ( super ) fn new ( ) -> Self {
387- Self {
388- registered_when : AtomicU64 :: new ( 0 ) ,
389- pointers : linked_list:: Pointers :: new ( ) ,
390- state : StateCell :: default ( ) ,
391- _p : PhantomPinned ,
390+ // ensure both scheduler handle and time driver are available,
391+ // otherwise panic
392+ let maybe_hdl =
393+ scheduler:: Handle :: with_current ( |hdl| hdl. driver ( ) . time . as_ref ( ) . map ( |_| hdl. clone ( ) ) ) ;
394+ match maybe_hdl {
395+ Some ( hdl) => Self {
396+ driver : hdl,
397+ registered_when : AtomicU64 :: new ( 0 ) ,
398+ pointers : linked_list:: Pointers :: new ( ) ,
399+ state : StateCell :: default ( ) ,
400+ _p : PhantomPinned ,
401+ } ,
402+ None => panic ! ( "{TIME_DISABLED_ERROR}" ) ,
392403 }
393404 }
394405
@@ -453,6 +464,10 @@ impl TimerShared {
453464 pub ( super ) fn might_be_registered ( & self ) -> bool {
454465 self . state . might_be_registered ( )
455466 }
467+
468+ fn driver ( & self ) -> & time:: Handle {
469+ self . driver . driver ( ) . time ( )
470+ }
456471}
457472
458473unsafe impl linked_list:: Link for TimerShared {
@@ -479,12 +494,8 @@ unsafe impl linked_list::Link for TimerShared {
479494
480495impl TimerEntry {
481496 #[ track_caller]
482- pub ( crate ) fn new ( handle : scheduler:: Handle , deadline : Instant ) -> Self {
483- // Panic if the time driver is not enabled
484- let _ = handle. driver ( ) . time ( ) ;
485-
497+ pub ( crate ) fn new ( deadline : Instant ) -> Self {
486498 Self {
487- driver : handle,
488499 inner : None ,
489500 deadline,
490501 registered : false ,
@@ -565,15 +576,14 @@ impl TimerEntry {
565576 // driver did so far and happens-before everything the driver does in
566577 // the future. While we have the lock held, we also go ahead and
567578 // deregister the entry if necessary.
568- unsafe { self . driver ( ) . clear_entry ( NonNull :: from ( inner) ) } ;
579+ unsafe { inner . driver ( ) . clear_entry ( NonNull :: from ( inner) ) } ;
569580 }
570581
571582 pub ( crate ) fn reset ( mut self : Pin < & mut Self > , new_time : Instant , reregister : bool ) {
572583 let this = self . as_mut ( ) . project ( ) ;
573584 * this. deadline = new_time;
574585 * this. registered = reregister;
575586
576- let tick = self . driver ( ) . time_source ( ) . deadline_to_tick ( new_time) ;
577587 let inner = match self . inner ( ) {
578588 Some ( inner) => inner,
579589 None => {
@@ -582,15 +592,17 @@ impl TimerEntry {
582592 . expect ( "inner should already be initialized by `this.init_inner()`" )
583593 }
584594 } ;
595+ let tick = inner. driver ( ) . time_source ( ) . deadline_to_tick ( new_time) ;
585596
586597 if inner. extend_expiration ( tick) . is_ok ( ) {
587598 return ;
588599 }
589600
590601 if reregister {
591602 unsafe {
592- self . driver ( )
593- . reregister ( & self . driver . driver ( ) . io , tick, inner. into ( ) ) ;
603+ inner
604+ . driver ( )
605+ . reregister ( & inner. driver . driver ( ) . io , tick, inner. into ( ) ) ;
594606 }
595607 }
596608 }
@@ -599,12 +611,6 @@ impl TimerEntry {
599611 mut self : Pin < & mut Self > ,
600612 cx : & mut Context < ' _ > ,
601613 ) -> Poll < Result < ( ) , super :: Error > > {
602- assert ! (
603- !self . driver( ) . is_shutdown( ) ,
604- "{}" ,
605- crate :: util:: error:: RUNTIME_SHUTTING_DOWN_ERROR
606- ) ;
607-
608614 if !self . registered {
609615 let deadline = self . deadline ;
610616 self . as_mut ( ) . reset ( deadline, true ) ;
@@ -613,16 +619,13 @@ impl TimerEntry {
613619 let inner = self
614620 . inner ( )
615621 . expect ( "inner should already be initialized by `self.reset()`" ) ;
616- inner. state . poll ( cx. waker ( ) )
617- }
618622
619- pub ( crate ) fn driver ( & self ) -> & super :: Handle {
620- self . driver . driver ( ) . time ( )
621- }
623+ assert ! (
624+ !inner. driver( ) . is_shutdown( ) ,
625+ "{RUNTIME_SHUTTING_DOWN_ERROR}"
626+ ) ;
622627
623- #[ cfg( all( tokio_unstable, feature = "tracing" ) ) ]
624- pub ( crate ) fn clock ( & self ) -> & super :: Clock {
625- self . driver . driver ( ) . clock ( )
628+ inner. state . poll ( cx. waker ( ) )
626629 }
627630}
628631
0 commit comments