pub struct Timer<T, N = SystemNow> { /* private fields */ }
Expand description
Timer implementation that drives Delay
, Interval
, and Timeout
.
A Timer
instance tracks the state necessary for managing time and
notifying the Delay
instances once their deadlines are reached.
It is expected that a single Timer
instance manages many individual
Delay
instances. The Timer
implementation is thread-safe and, as such,
is able to handle callers from across threads.
Callers do not use Timer
directly to create Delay
instances. Instead,
Handle
is used. A handle for the timer instance is obtained by calling
handle
. Handle
is the type that implements Clone
and is Send + Sync
.
After creating the Timer
instance, the caller must repeatedly call
turn
. The timer will perform no work unless turn
is called
repeatedly.
The Timer
has a resolution of one millisecond. Any unit of time that falls
between milliseconds are rounded up to the next millisecond.
When the Timer
instance is dropped, any outstanding Delay
instance that
has not elapsed will be notified with an error. At this point, calling
poll
on the Delay
instance will result in Err
being returned.
§Implementation
Timer
is based on the paper by Varghese and Lauck.
A hashed timing wheel is a vector of slots, where each slot handles a time slice. As time progresses, the timer walks over the slot for the current instant, and processes each entry for that slot. When the timer reaches the end of the wheel, it starts again at the beginning.
The Timer
implementation maintains six wheels arranged in a set of levels.
As the levels go up, the slots of the associated wheel represent larger
intervals of time. At each level, the wheel has 64 slots. Each slot covers a
range of time equal to the wheel at the lower level. At level zero, each
slot represents one millisecond of time.
The wheels are:
- Level 0: 64 x 1 millisecond slots.
- Level 1: 64 x 64 millisecond slots.
- Level 2: 64 x ~4 second slots.
- Level 3: 64 x ~4 minute slots.
- Level 4: 64 x ~4 hour slots.
- Level 5: 64 x ~12 day slots.
When the timer processes entries at level zero, it will notify all the
Delay
instances as their deadlines have been reached. For all higher
levels, all entries will be redistributed across the wheel at the next level
down. Eventually, as time progresses, entries will Delay
instances will
either be canceled (dropped) or their associated entries will reach level
zero and be notified.
Implementations§
Source§impl<T, N> Timer<T, N>where
T: Park,
N: Now,
impl<T, N> Timer<T, N>where
T: Park,
N: Now,
Sourcepub fn new_with_now(park: T, now: N) -> Self
pub fn new_with_now(park: T, now: N) -> Self
Create a new Timer
instance that uses park
to block the current
thread and now
to get the current Instant
.
Specifying the source of time is useful when testing.
Sourcepub fn handle(&self) -> Handle
pub fn handle(&self) -> Handle
Returns a handle to the timer.
The Handle
is how Delay
instances are created. The Delay
instances
can either be created directly or the Handle
instance can be passed to
with_default
, setting the timer as the default timer for the execution
context.
Sourcepub fn turn(&mut self, max_wait: Option<Duration>) -> Result<Turn, T::Error>
pub fn turn(&mut self, max_wait: Option<Duration>) -> Result<Turn, T::Error>
Performs one iteration of the timer loop.
This function must be called repeatedly in order for the Timer
instance to make progress. This is where the work happens.
The Timer
will use the Park
instance that was specified in new
to block the current thread until the next Delay
instance elapses. One
call to turn
results in at most one call to park.park()
.
§Return
On success, Ok(Turn)
is returned, where Turn
is a placeholder type
that currently does nothing but may, in the future, have functions add
to provide information about the call to turn
.
If the call to park.park()
fails, then Err
is returned with the
error.