Skip to main content

wallclock_timer/timers/
mod.rs

1use std::{fmt, hash::Hash, time::SystemTime};
2
3/// Chrono-related scheduling helpers.
4///
5/// Allows scheduling directory with [[::chrono::DateTime]] instances.
6#[cfg(feature = "chrono")]
7#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))]
8pub mod chrono;
9
10/// A trait for state that can be triggered once.
11pub trait State {
12    /// The type of the unique id of the outstanding timeout.
13    type Id: Hash + Clone + Eq;
14
15    /// A reference to the id associated with this state.
16    fn id(&self) -> &Self::Id;
17
18    /// Trigger is called by the timer implementation
19    /// when the timeout has expired.
20    fn trigger(self);
21}
22
23/// A low-level wall-clock timer API.
24pub trait WallClockTimer {
25    /// A type to uniquely identify any timeout to be scheduled or cancelled.
26    type Id: Hash + Clone + Eq + Ord;
27    /// The type of state to keep for timers.
28    type State: State<Id = Self::Id>;
29    /// Error type produced by timer operations.
30    type Error: std::error::Error + Send + Sync + 'static;
31
32    /// Schedule the `state` to be triggered at the given wall-clock `deadline`.
33    fn schedule_at(&mut self, deadline: SystemTime, state: Self::State) -> Result<(), Self::Error>;
34
35    /// Cancel the timer indicated by the unique `id`.
36    fn cancel(&mut self, id: Self::Id) -> Result<(), Self::Error>;
37}
38
39/// A timeout state for a timer using a closure as the triggering action.
40pub struct ClosureState<I> {
41    id: I,
42    action: Box<dyn FnOnce(I) + Send + 'static>,
43}
44
45impl<I> ClosureState<I> {
46    /// Produces a new instance of this state type
47    /// from a unique id and the action to be executed when it expires.
48    pub fn new<F>(id: I, action: F) -> Self
49    where
50        F: FnOnce(I) + Send + 'static,
51    {
52        ClosureState {
53            id,
54            action: Box::new(action),
55        }
56    }
57}
58
59impl<I> State for ClosureState<I>
60where
61    I: Hash + Clone + Eq,
62{
63    type Id = I;
64
65    fn id(&self) -> &Self::Id {
66        &self.id
67    }
68
69    fn trigger(self) {
70        (self.action)(self.id)
71    }
72}
73
74impl<I> fmt::Debug for ClosureState<I>
75where
76    I: Hash + Clone + Eq + fmt::Debug,
77{
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        write!(f, "ClosureState(id={:?}, action=<function>)", self.id)
80    }
81}
82
83/// Convenience API for timers that use the closure state types.
84pub trait ClosureTimer: WallClockTimer {
85    /// Schedule `action` to be executed at `deadline`.
86    fn schedule_action_at<F>(
87        &mut self,
88        id: Self::Id,
89        deadline: std::time::SystemTime,
90        action: F,
91    ) -> Result<(), Self::Error>
92    where
93        F: FnOnce(Self::Id) + Send + 'static;
94}
95
96impl<I, T> ClosureTimer for T
97where
98    I: Hash + Clone + Eq,
99    T: WallClockTimer<Id = I, State = ClosureState<I>>,
100{
101    fn schedule_action_at<F>(
102        &mut self,
103        id: Self::Id,
104        deadline: std::time::SystemTime,
105        action: F,
106    ) -> Result<(), Self::Error>
107    where
108        F: FnOnce(Self::Id) + Send + 'static,
109    {
110        self.schedule_at(deadline, ClosureState::new(id, action))
111    }
112}
113
114/// A shorthand for closure timers that use UUIDs as ids.
115#[cfg(feature = "uuid")]
116pub type UuidClosureTimerRef = crate::thread_timer::ClosureTimerRef<uuid::Uuid>;