pub struct TimerWheel<T> { /* private fields */ }Expand description
High-performance hierarchical timing wheel
Uses a two-level hierarchy to efficiently handle timers across a wide time range:
- L0 (Fast wheel): Handles near-term timers (0 to ~1 second)
- Fine-grained resolution for accurate short-term scheduling
- Polled frequently for expired timers
- L1 (Medium wheel): Handles long-term timers (~1 second to ~18 minutes)
- Coarser resolution to reduce memory overhead
- Timers cascade down to L0 as their deadline approaches
The hierarchy allows O(1) scheduling and cancellation while supporting a wide range of timer durations without excessive memory usage.
Implementations§
Source§impl<T> TimerWheel<T>
impl<T> TimerWheel<T>
Sourcepub fn new(
tick_resolution: Duration,
ticks_per_wheel: usize,
worker_id: u32,
) -> Self
pub fn new( tick_resolution: Duration, ticks_per_wheel: usize, worker_id: u32, ) -> Self
Create new hierarchical timer wheel
§Arguments
tick_resolution- L0 tick duration (must be power of 2 nanoseconds, typically 1.05ms)ticks_per_wheel- Number of spokes per wheel (must be power of 2, typically 1024)worker_id- Worker ID that owns this timer wheel
§Timer Deadlines
All timer deadlines are specified as nanoseconds elapsed since wheel creation.
Sourcepub fn with_allocation(
tick_resolution: Duration,
ticks_per_wheel: usize,
initial_tick_allocation: usize,
worker_id: u32,
) -> Self
pub fn with_allocation( tick_resolution: Duration, ticks_per_wheel: usize, initial_tick_allocation: usize, worker_id: u32, ) -> Self
Create hierarchical timer wheel with custom initial allocation per tick
§Arguments
tick_resolution- L0 tick duration (must be power of 2 nanoseconds)ticks_per_wheel- Number of spokes per wheel (must be power of 2)initial_tick_allocation- Initial slots per tick (must be power of 2)worker_id- Worker ID that owns this timer wheel
§Design Notes
The L1 tick resolution equals one full L0 rotation, creating a natural cascading relationship: when an L1 tick expires, all its timers are within L0’s coverage range and can be cascaded down.
Sourcepub fn schedule_timer(
&mut self,
deadline_ns: u64,
data: T,
) -> Result<u64, TimerWheelError>
pub fn schedule_timer( &mut self, deadline_ns: u64, data: T, ) -> Result<u64, TimerWheelError>
Schedule a timer for an absolute deadline
The deadline is specified as nanoseconds since wheel creation. The timer is automatically placed in the appropriate wheel (L0 for near-term, L1 for long-term) based on the deadline value.
§Arguments
deadline_ns- Absolute deadline in nanoseconds (must be > 0 and in the future)data- User data to associate with this timer
§Returns
Returns a timer ID that can be used to cancel the timer, or an error if the deadline is invalid or capacity is exceeded.
Sourcepub fn cancel_timer(
&mut self,
timer_id: u64,
) -> Result<Option<T>, TimerWheelError>
pub fn cancel_timer( &mut self, timer_id: u64, ) -> Result<Option<T>, TimerWheelError>
Sourcepub fn poll(
&mut self,
now_ns: u64,
expiry_limit: usize,
output: &mut Vec<(u64, u64, T)>,
) -> usize
pub fn poll( &mut self, now_ns: u64, expiry_limit: usize, output: &mut Vec<(u64, u64, T)>, ) -> usize
Poll for expired timers
Checks for timers that have expired by the given now_ns time. First cascades
L1 timers that are now within L0 coverage down to L0, then polls L0 for
expired timers.
§Arguments
now_ns- Current time in nanosecondsexpiry_limit- Maximum number of expired timers to returnoutput- Buffer to write expired timer tuples:(timer_id, deadline_ns, data)
§Returns
Returns the number of expired timers found (may be less than expiry_limit)
Sourcepub fn advance_to(&mut self, now_ns: u64)
pub fn advance_to(&mut self, now_ns: u64)
Advance the wheel’s current tick position without polling
Useful for synchronizing the wheel’s position when time advances without immediately processing expired timers.
Sourcepub fn current_tick_time_ns(&self) -> u64
pub fn current_tick_time_ns(&self) -> u64
Get the time corresponding to the next tick
Returns the absolute time (in nanoseconds) when the next tick will occur.
Sourcepub fn timer_count(&self) -> u64
pub fn timer_count(&self) -> u64
Get the total number of active timers across both wheels
Sourcepub fn next_deadline(&mut self) -> Option<u64>
pub fn next_deadline(&mut self) -> Option<u64>
Get the earliest deadline among all active timers
Uses cached values when available for O(1) performance. Falls back to full wheel scans when cache is invalidated (O(ticks_per_wheel × tick_allocation)).
§Returns
Returns the earliest deadline in nanoseconds, or None if no timers are scheduled.