timestamp_source/
lib.rs

1//! Timestamp source library provides simple traits for handling timestamps.
2
3#![no_std]
4
5use core::marker::PhantomData;
6use spin::relax::{RelaxStrategy, Spin};
7
8/// Represents a timestamp.
9pub trait Timestamp {
10    type Duration: PartialOrd;
11    type Error;
12
13    /// Get current timestamp.
14    fn now() -> Self;
15
16    /// Get duration since start.
17    fn duration_since_epoch(self) -> Self::Duration;
18
19    /// Get duration since `other`.
20    /// # Errors
21    /// This function will return an error if duration between other-self timestamps is negative.
22    fn duration_since(&self, other: &Self) -> Result<Self::Duration, Self::Error>;
23}
24
25/// Represents an elapsed timer.
26pub trait ElapsedTimer {
27    type Timestamp: Timestamp;
28
29    /// Returns true if a timer duration is more(equal) then duration between from-to timestamps,
30    /// otherwise false.
31    /// # Errors
32    /// This function will return an error if duration between from-to timestamps is negative.
33    fn timeout(
34        &self,
35        from: &Self::Timestamp,
36        to: &Self::Timestamp,
37    ) -> Result<bool, <Self::Timestamp as Timestamp>::Error>;
38}
39
40/// Implementation of [`ElapsedTimer`](crate::ElapsedTimer)
41pub struct Timer<T: Timestamp> {
42    duration: T::Duration,
43}
44
45impl<T: Timestamp> Timer<T> {
46    /// Creates a new [`Timer<T>`].
47    pub const fn new(duration: T::Duration) -> Self {
48        Timer { duration }
49    }
50
51    /// Borrow the duration of this [`Timer<T>`].
52    pub fn borrow_duration(&self) -> &T::Duration {
53        &self.duration
54    }
55
56    /// Borrow the mutable duration of this [`Timer<T>`].
57    pub fn borrow_mut_duration(&mut self) -> &mut T::Duration {
58        &mut self.duration
59    }
60}
61
62impl<T: Timestamp> ElapsedTimer for Timer<T> {
63    type Timestamp = T;
64
65    fn timeout(
66        &self,
67        from: &Self::Timestamp,
68        to: &Self::Timestamp,
69    ) -> Result<bool, <Self::Timestamp as Timestamp>::Error> {
70        Ok(to.duration_since(from)? >= self.duration)
71    }
72}
73
74/// Object that can delay by some duration.
75///
76/// `T` - [`Timestamp`] that provides `now`.
77///
78/// `R` - [`RelaxStrategy`] that provides a strategy to handle an idle.
79pub struct Delay<T: Timestamp, R: RelaxStrategy = Spin> {
80    duration: T::Duration,
81    relax: PhantomData<R>,
82}
83
84impl<T: Timestamp, R: RelaxStrategy> Delay<T, R> {
85    /// Creates a new [`Delay<T, R>`].
86    pub const fn new(duration: T::Duration) -> Self {
87        Delay {
88            duration,
89            relax: PhantomData::<R>,
90        }
91    }
92
93    /// Borrow the duration of this [`Delay<T, R>`].
94    pub fn borrow_duration(&self) -> &T::Duration {
95        &self.duration
96    }
97
98    /// Borrow the mutable duration of this [`Delay<T, R>`].
99    pub fn borrow_mut_duration(&mut self) -> &mut T::Duration {
100        &mut self.duration
101    }
102
103    /// Execute delay.
104    /// # Errors
105    /// This function will return an error if [`Timestamp::duration_since`] returns an error.
106    pub fn exec(&self) -> Result<(), T::Error> {
107        let start = T::now();
108
109        while T::now().duration_since(&start)? < self.duration {
110            R::relax();
111        }
112
113        Ok(())
114    }
115}