mod byte_wheel;
mod quad_wheel;
pub(crate) mod raw_wheel;
use crate::{cfg_not_sync, cfg_sync, wheels::read::Haw};
use core::{fmt::Debug, hash::Hash, time::Duration};
pub(super) use raw_wheel::RawTimerWheel;
use crate::{Aggregator, duration};
use core::{fmt, fmt::Display};
#[derive(PartialEq, Debug)]
pub enum Skip {
Empty,
Millis(u32),
None,
}
impl Skip {
pub fn from_millis(ms: u32) -> Skip {
if ms == 0 {
Skip::None
} else {
Skip::Millis(ms)
}
}
pub fn empty() -> Skip {
Skip::Empty
}
}
pub trait TimerEntryWithDelay: Debug {
fn delay(&self) -> Duration;
}
#[derive(Debug)]
pub enum TimerError<EntryType> {
NotFound,
Expired(EntryType),
}
#[derive(Debug)]
pub struct IdOnlyTimerEntry<I> {
pub id: I,
pub delay: Duration,
}
impl<I> IdOnlyTimerEntry<I> {
pub fn new(id: I, delay: Duration) -> Self {
IdOnlyTimerEntry { id, delay }
}
pub fn id(&self) -> &I {
&self.id
}
}
impl<I> TimerEntryWithDelay for IdOnlyTimerEntry<I>
where
I: Hash + Clone + Eq + core::fmt::Debug,
{
fn delay(&self) -> Duration {
self.delay
}
}
#[derive(Debug)]
pub struct TimerExpiredError<T: Debug> {
pub current_time: u64,
pub scheduled_time: u64,
pub entry: T,
}
impl<T: Debug> Display for TimerExpiredError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Attempted to schedule timer entry {:?} at {} when time is {}",
self.entry, self.scheduled_time, self.current_time
)
}
}
#[cfg(not(feature = "std"))]
use alloc::boxed::Box;
pub type WheelFn<A> = Box<dyn Fn(&Haw<A>)>;
pub enum TimerAction<A: Aggregator> {
Oneshot(WheelFn<A>),
Repeat((u64, duration::Duration, WheelFn<A>)),
}
cfg_not_sync! {
#[cfg(not(feature = "std"))]
use alloc::rc::Rc;
use core::cell::RefCell;
#[cfg(feature = "std")]
use std::rc::Rc;
pub type TimerRef<'a, T> = core::cell::Ref<'a, RawTimerWheel<TimerAction<T>>>;
pub type TimerRefMut<'a, T> = core::cell::RefMut<'a, RawTimerWheel<TimerAction<T>>>;
#[derive(Clone, Default)]
#[doc(hidden)]
pub struct TimerWheel<T: Aggregator>(Rc<RefCell<RawTimerWheel<TimerAction<T>>>>);
impl<T: Aggregator> TimerWheel<T> {
#[inline(always)]
pub fn new(val: RawTimerWheel<TimerAction<T>>) -> Self {
Self(Rc::new(RefCell::new(val)))
}
#[inline(always)]
pub fn read(&self) -> TimerRef<'_, T> {
self.0.borrow()
}
#[inline(always)]
pub fn write(&self) -> TimerRefMut<'_, T> {
self.0.borrow_mut()
}
}
}
cfg_sync! {
use parking_lot::{MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock};
use std::sync::Arc;
pub type TimerRef<'a, T> = MappedRwLockReadGuard<'a, RawTimerWheel<TimerAction<T>>>;
pub type TimerRefMut<'a, T> = MappedRwLockWriteGuard<'a, RawTimerWheel<TimerAction<T>>>;
#[derive(Clone, Default)]
#[doc(hidden)]
pub struct TimerWheel<T: Aggregator>(Arc<RwLock<RawTimerWheel<TimerAction<T>>>>);
impl<T: Aggregator> TimerWheel<T> {
#[inline(always)]
pub fn new(val: RawTimerWheel<TimerAction<T>>) -> Self {
Self(Arc::new(RwLock::new(val)))
}
#[inline(always)]
pub fn read(&self) -> TimerRef<'_, T> {
parking_lot::RwLockReadGuard::map(self.0.read(), |v| v)
}
#[inline(always)]
pub fn write(&self) -> TimerRefMut<'_, T> {
parking_lot::RwLockWriteGuard::map(self.0.write(), |v| v)
}
}
}