use std::collections::HashMap;
pub struct TimerWheel<V> {
slots: Vec<Slot<V>>,
mask: usize,
hand: usize,
next_id: u64,
id_to_slot: HashMap<u64, usize>,
}
struct Slot<V> {
entries: Vec<Entry<V>>,
}
struct Entry<V> {
id: u64,
rounds: u32,
value: V,
cancelled: bool,
}
impl<V> TimerWheel<V> {
pub fn new(num_slots: usize) -> Self {
let n = num_slots.max(2).next_power_of_two();
let mut slots = Vec::with_capacity(n);
for _ in 0..n {
slots.push(Slot {
entries: Vec::new(),
});
}
Self {
slots,
mask: n - 1,
hand: 0,
next_id: 1,
id_to_slot: HashMap::new(),
}
}
pub fn num_slots(&self) -> usize {
self.slots.len()
}
pub fn schedule(&mut self, delay_ticks: usize, value: V) -> u64 {
let target = self.hand.wrapping_add(delay_ticks);
let slot = target & self.mask;
let rounds = (delay_ticks / self.slots.len()) as u32;
let id = self.next_id;
self.next_id += 1;
self.slots[slot].entries.push(Entry {
id,
rounds,
value,
cancelled: false,
});
self.id_to_slot.insert(id, slot);
id
}
pub fn cancel(&mut self, id: u64) -> bool {
let Some(&slot) = self.id_to_slot.get(&id) else {
return false;
};
for e in &mut self.slots[slot].entries {
if e.id == id && !e.cancelled {
e.cancelled = true;
return true;
}
}
false
}
pub fn tick(&mut self) -> Vec<V> {
self.hand = (self.hand + 1) & self.mask;
let slot = self.hand;
let mut fired = Vec::new();
let entries = std::mem::take(&mut self.slots[slot].entries);
let mut survivors = Vec::new();
for mut e in entries {
if e.cancelled {
self.id_to_slot.remove(&e.id);
continue;
}
if e.rounds == 0 {
self.id_to_slot.remove(&e.id);
fired.push(e.value);
} else {
e.rounds -= 1;
survivors.push(e);
}
}
self.slots[slot].entries = survivors;
fired
}
}
#[cfg(feature = "harness")]
pub mod recipe;
#[cfg(any(
feature = "hierarchical",
feature = "concurrent",
feature = "deadline-scheduler",
feature = "cron",
feature = "metrics",
))]
pub mod features;
#[cfg(feature = "concurrent")]
pub use features::concurrent::ConcurrentTimerWheel;
#[cfg(feature = "cron")]
pub use features::cron::{CronError, CronSchedule, CronScheduler};
#[cfg(feature = "deadline-scheduler")]
pub use features::deadline_scheduler::{Clock, DeadlineScheduler, MonotonicClock, TestClock};
#[cfg(feature = "hierarchical")]
pub use features::hierarchical::HierarchicalTimerWheel;
#[cfg(feature = "metrics")]
pub use features::metrics::{MeteredTimerWheel, TimerMetrics};