21
21
//!
22
22
//! Each timer has a state field associated with it. This field contains either
23
23
//! the current scheduled time, or a special flag value indicating its state.
24
- //! This state can either indicate that the timer is on the 'pending' queue (and
25
- //! thus will be fired with an `Ok(())` result soon) or that it has already been
26
- //! fired/deregistered.
24
+ //! This state can either indicate that the timer is firing (and thus will be fired
25
+ //! with an `Ok(())` result soon) or that it has already been fired/deregistered.
27
26
//!
28
27
//! This single state field allows for code that is firing the timer to
29
28
//! synchronize with any racing `reset` calls reliably.
49
48
//! There is of course a race condition between timer reset and timer
50
49
//! expiration. If the driver fails to observe the updated expiration time, it
51
50
//! could trigger expiration of the timer too early. However, because
52
- //! [`mark_pending `][mark_pending ] performs a compare-and-swap, it will identify this race and
53
- //! refuse to mark the timer as pending .
51
+ //! [`mark_firing `][mark_firing ] performs a compare-and-swap, it will identify this race and
52
+ //! refuse to mark the timer as firing .
54
53
//!
55
- //! [mark_pending ]: TimerHandle::mark_pending
54
+ //! [mark_firing ]: TimerHandle::mark_firing
56
55
57
56
use crate :: loom:: cell:: UnsafeCell ;
58
57
use crate :: loom:: sync:: atomic:: AtomicU64 ;
@@ -70,9 +69,9 @@ use std::{marker::PhantomPinned, pin::Pin, ptr::NonNull};
70
69
71
70
type TimerResult = Result < ( ) , crate :: time:: error:: Error > ;
72
71
73
- const STATE_DEREGISTERED : u64 = u64:: MAX ;
74
- const STATE_PENDING_FIRE : u64 = STATE_DEREGISTERED - 1 ;
75
- const STATE_MIN_VALUE : u64 = STATE_PENDING_FIRE ;
72
+ pub ( super ) const STATE_DEREGISTERED : u64 = u64:: MAX ;
73
+ const STATE_FIRING : u64 = STATE_DEREGISTERED - 1 ;
74
+ const STATE_MIN_VALUE : u64 = STATE_FIRING ;
76
75
/// The largest safe integer to use for ticks.
77
76
///
78
77
/// This value should be updated if any other signal values are added above.
@@ -123,10 +122,6 @@ impl StateCell {
123
122
}
124
123
}
125
124
126
- fn is_pending ( & self ) -> bool {
127
- self . state . load ( Ordering :: Relaxed ) == STATE_PENDING_FIRE
128
- }
129
-
130
125
/// Returns the current expiration time, or None if not currently scheduled.
131
126
fn when ( & self ) -> Option < u64 > {
132
127
let cur_state = self . state . load ( Ordering :: Relaxed ) ;
@@ -162,26 +157,28 @@ impl StateCell {
162
157
}
163
158
}
164
159
165
- /// Marks this timer as being moved to the pending list, if its scheduled
166
- /// time is not after `not_after`.
160
+ /// Marks this timer firing, if its scheduled time is not after `not_after`.
167
161
///
168
162
/// If the timer is scheduled for a time after `not_after`, returns an Err
169
163
/// containing the current scheduled time.
170
164
///
171
165
/// SAFETY: Must hold the driver lock.
172
- unsafe fn mark_pending ( & self , not_after : u64 ) -> Result < ( ) , u64 > {
166
+ unsafe fn mark_firing ( & self , not_after : u64 ) -> Result < ( ) , u64 > {
173
167
// Quick initial debug check to see if the timer is already fired. Since
174
168
// firing the timer can only happen with the driver lock held, we know
175
169
// we shouldn't be able to "miss" a transition to a fired state, even
176
170
// with relaxed ordering.
177
171
let mut cur_state = self . state . load ( Ordering :: Relaxed ) ;
178
-
179
172
loop {
173
+ // Because its state is STATE_DEREGISTERED, it has been fired.
174
+ if cur_state == STATE_DEREGISTERED {
175
+ break Err ( cur_state) ;
176
+ }
180
177
// improve the error message for things like
181
178
// https://github.com/tokio-rs/tokio/issues/3675
182
179
assert ! (
183
180
cur_state < STATE_MIN_VALUE ,
184
- "mark_pending called when the timer entry is in an invalid state"
181
+ "mark_firing called when the timer entry is in an invalid state"
185
182
) ;
186
183
187
184
if cur_state > not_after {
@@ -190,7 +187,7 @@ impl StateCell {
190
187
191
188
match self . state . compare_exchange_weak (
192
189
cur_state,
193
- STATE_PENDING_FIRE ,
190
+ STATE_FIRING ,
194
191
Ordering :: AcqRel ,
195
192
Ordering :: Acquire ,
196
193
) {
@@ -337,11 +334,6 @@ pub(crate) struct TimerShared {
337
334
/// Only accessed under the entry lock.
338
335
pointers : linked_list:: Pointers < TimerShared > ,
339
336
340
- /// The expiration time for which this entry is currently registered.
341
- /// Generally owned by the driver, but is accessed by the entry when not
342
- /// registered.
343
- cached_when : AtomicU64 ,
344
-
345
337
/// Current state. This records whether the timer entry is currently under
346
338
/// the ownership of the driver, and if not, its current state (not
347
339
/// complete, fired, error, etc).
@@ -356,7 +348,6 @@ unsafe impl Sync for TimerShared {}
356
348
impl std:: fmt:: Debug for TimerShared {
357
349
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
358
350
f. debug_struct ( "TimerShared" )
359
- . field ( "cached_when" , & self . cached_when . load ( Ordering :: Relaxed ) )
360
351
. field ( "state" , & self . state )
361
352
. finish ( )
362
353
}
@@ -374,40 +365,12 @@ impl TimerShared {
374
365
pub ( super ) fn new ( shard_id : u32 ) -> Self {
375
366
Self {
376
367
shard_id,
377
- cached_when : AtomicU64 :: new ( 0 ) ,
378
368
pointers : linked_list:: Pointers :: new ( ) ,
379
369
state : StateCell :: default ( ) ,
380
370
_p : PhantomPinned ,
381
371
}
382
372
}
383
373
384
- /// Gets the cached time-of-expiration value.
385
- pub ( super ) fn cached_when ( & self ) -> u64 {
386
- // Cached-when is only accessed under the driver lock, so we can use relaxed
387
- self . cached_when . load ( Ordering :: Relaxed )
388
- }
389
-
390
- /// Gets the true time-of-expiration value, and copies it into the cached
391
- /// time-of-expiration value.
392
- ///
393
- /// SAFETY: Must be called with the driver lock held, and when this entry is
394
- /// not in any timer wheel lists.
395
- pub ( super ) unsafe fn sync_when ( & self ) -> u64 {
396
- let true_when = self . true_when ( ) ;
397
-
398
- self . cached_when . store ( true_when, Ordering :: Relaxed ) ;
399
-
400
- true_when
401
- }
402
-
403
- /// Sets the cached time-of-expiration value.
404
- ///
405
- /// SAFETY: Must be called with the driver lock held, and when this entry is
406
- /// not in any timer wheel lists.
407
- unsafe fn set_cached_when ( & self , when : u64 ) {
408
- self . cached_when . store ( when, Ordering :: Relaxed ) ;
409
- }
410
-
411
374
/// Returns the true time-of-expiration value, with relaxed memory ordering.
412
375
pub ( super ) fn true_when ( & self ) -> u64 {
413
376
self . state . when ( ) . expect ( "Timer already fired" )
@@ -420,7 +383,6 @@ impl TimerShared {
420
383
/// in the timer wheel.
421
384
pub ( super ) unsafe fn set_expiration ( & self , t : u64 ) {
422
385
self . state . set_expiration ( t) ;
423
- self . cached_when . store ( t, Ordering :: Relaxed ) ;
424
386
}
425
387
426
388
/// Sets the true time-of-expiration only if it is after the current.
@@ -590,16 +552,8 @@ impl TimerEntry {
590
552
}
591
553
592
554
impl TimerHandle {
593
- pub ( super ) unsafe fn cached_when ( & self ) -> u64 {
594
- unsafe { self . inner . as_ref ( ) . cached_when ( ) }
595
- }
596
-
597
- pub ( super ) unsafe fn sync_when ( & self ) -> u64 {
598
- unsafe { self . inner . as_ref ( ) . sync_when ( ) }
599
- }
600
-
601
- pub ( super ) unsafe fn is_pending ( & self ) -> bool {
602
- unsafe { self . inner . as_ref ( ) . state . is_pending ( ) }
555
+ pub ( super ) unsafe fn true_when ( & self ) -> u64 {
556
+ unsafe { self . inner . as_ref ( ) . true_when ( ) }
603
557
}
604
558
605
559
/// Forcibly sets the true and cached expiration times to the given tick.
@@ -610,27 +564,16 @@ impl TimerHandle {
610
564
self . inner . as_ref ( ) . set_expiration ( tick) ;
611
565
}
612
566
613
- /// Attempts to mark this entry as pending . If the expiration time is after
567
+ /// Attempts to mark this entry as firing . If the expiration time is after
614
568
/// `not_after`, however, returns an Err with the current expiration time.
615
569
///
616
570
/// If an `Err` is returned, the `cached_when` value will be updated to this
617
571
/// new expiration time.
618
572
///
619
573
/// SAFETY: The caller must ensure that the handle remains valid, the driver
620
574
/// lock is held, and that the timer is not in any wheel linked lists.
621
- /// After returning Ok, the entry must be added to the pending list.
622
- pub ( super ) unsafe fn mark_pending ( & self , not_after : u64 ) -> Result < ( ) , u64 > {
623
- match self . inner . as_ref ( ) . state . mark_pending ( not_after) {
624
- Ok ( ( ) ) => {
625
- // mark this as being on the pending queue in cached_when
626
- self . inner . as_ref ( ) . set_cached_when ( u64:: MAX ) ;
627
- Ok ( ( ) )
628
- }
629
- Err ( tick) => {
630
- self . inner . as_ref ( ) . set_cached_when ( tick) ;
631
- Err ( tick)
632
- }
633
- }
575
+ pub ( super ) unsafe fn mark_firing ( & self , not_after : u64 ) -> Result < ( ) , u64 > {
576
+ self . inner . as_ref ( ) . state . mark_firing ( not_after)
634
577
}
635
578
636
579
/// Attempts to transition to a terminal state. If the state is already a
0 commit comments