embedded_timers/
instant.rs

1// Copyright Open Logistics Foundation
2//
3// Licensed under the Open Logistics Foundation License 1.3.
4// For details on the licensing terms, see the LICENSE file.
5// SPDX-License-Identifier: OLFL-1.3
6
7//! Defines the [`Instant`] trait for clock users and corresponding implementations for clock
8//! implementers
9//!
10//! The following types implementing the [`Instant`] trait are defined:
11//! - [`TimespecInstant`] for a struct of `u32` seconds and `u32` nanoseconds
12//! - [`Instant32`] for an instant using a single `u32` tick counter
13//! - [`Instant64`] for an instant using a single `u64` tick counter
14//! - If the `std` feature is enabled, the `Instant` trait is implemented on `std::time::Instant`
15
16use core::time::Duration;
17
18use core::any::Any;
19use core::borrow::{Borrow, BorrowMut};
20use core::fmt::Debug;
21use core::hash::Hash;
22use core::ops::{Add, AddAssign, Sub, SubAssign};
23use core::panic::{RefUnwindSafe, UnwindSafe};
24
25use core::convert::TryInto;
26
27// Structural(Partial)Eq behind unstable feature, see https://github.com/rust-lang/rust/issues/31434
28//use core::marker::{StructuralEq, StructuralPartialEq};
29
30/// Trait for types which represent measurements of monotonically nondecreasing clocks
31///
32/// This is heavily inspired by the Rust stdlib's
33/// [`std::time::Instant`](https://doc.rust-lang.org/stable/std/time/struct.Instant.html) type and
34/// tries to replicate its behaviour wherever possible. In contrast to `std::time::Instant` which
35/// relies on a globally available clock, this trait only describes the behavior which is available
36/// without a global clock. Everything which requires a global clock is moved to the
37/// [`Clock`](crate::clock::Clock) trait.
38///
39/// To be implemented on a given type, this trait requires that type to implement the same traits
40/// as `std::time::Instant`. This might look like a huge constraint for implementers at first,
41/// but it actually gives more possibilities to users. And it seems reasonable to require all these
42/// traits because the underlying data structure will most probably just be a struct containing
43/// some kind of numbers (which should not be NaN).
44pub trait Instant:
45      Sized
46    + Add<Duration, Output=Self>
47    + AddAssign<Duration>
48    + Clone
49    + Copy
50    + Debug
51    + Eq
52    + Hash
53    + Ord
54    + PartialEq<Self>
55    + PartialOrd<Self>
56    // Structural(Partial)Eq behind unstable feature, see
57    // https://github.com/rust-lang/rust/issues/31434
58    //+ StructuralEq
59    //+ StructuralPartialEq
60    + Sub<Duration, Output=Self>
61    + Sub<Self, Output=Duration>
62    + SubAssign<Duration>
63    + RefUnwindSafe
64    + Send
65    + Sync
66    + Unpin
67    + UnwindSafe
68    + Any
69    // TODO Do the following trait bounds even make sense?
70    + Borrow<Self>
71    + BorrowMut<Self>
72    + From<Self>
73    //+ core::borrow::ToOwned does not exist, only std::borrow::ToOwned
74{
75    /// Returns the amount of time elapsed from another instant to this one, or zero duration if
76    /// that instant is later than this one.
77    ///
78    /// # Panics
79    ///
80    /// As in the current version of the Rust stdlib, this method saturates instead of panicking.
81    ///
82    /// # Examples
83    ///
84    /// ```no_run
85    /// use core::time::Duration;
86    /// use embedded_timers::instant::Instant;
87    /// use embedded_timers::clock::Clock;
88    /// # use embedded_timers::instant::Instant32;
89    /// # fn sleep(_duration: Duration) {}
90    /// # struct MyClock;
91    /// # impl embedded_timers::clock::Clock for MyClock {
92    /// #     type Instant = Instant32<1000>;
93    /// #     fn now(&self) -> Instant32<1000> {
94    /// #         Instant32::new(0)
95    /// #     }
96    /// # }
97    ///
98    /// let clock = MyClock;
99    /// let now = clock.now();
100    /// sleep(Duration::new(1, 0));
101    /// let new_now = clock.now();
102    /// println!("{:?}", new_now.duration_since(now));
103    /// println!("{:?}", now.duration_since(new_now)); // 0ns
104    /// ```
105    #[must_use]
106    fn duration_since(&self, earlier: Self) -> Duration {
107        self.checked_duration_since(earlier).unwrap_or_default()
108    }
109
110    /// Returns the amount of time elapsed from another instant to this one, or None if that
111    /// instant is later than this one.
112    ///
113    /// # Examples
114    ///
115    /// ```no_run
116    /// use core::time::Duration;
117    /// use embedded_timers::instant::Instant;
118    /// use embedded_timers::clock::Clock;
119    /// # use embedded_timers::instant::Instant32;
120    /// # fn sleep(_duration: Duration) {}
121    /// # struct MyClock;
122    /// # impl embedded_timers::clock::Clock for MyClock {
123    /// #     type Instant = Instant32<1000>;
124    /// #     fn now(&self) -> Instant32<1000> {
125    /// #         Instant32::new(0)
126    /// #     }
127    /// # }
128    ///
129    /// let clock = MyClock;
130    /// let now = clock.now();
131    /// sleep(Duration::new(1, 0));
132    /// let new_now = clock.now();
133    /// println!("{:?}", new_now.checked_duration_since(now));
134    /// println!("{:?}", now.checked_duration_since(new_now)); // None
135    /// ```
136    #[must_use]
137    fn checked_duration_since(&self, earlier: Self) -> Option<Duration>;
138
139    /// Returns the amount of time elapsed from another instant to this one, or zero duration if
140    /// that instant is later than this one.
141    ///
142    /// # Examples
143    ///
144    /// ```no_run
145    /// use core::time::Duration;
146    /// use embedded_timers::instant::Instant;
147    /// use embedded_timers::clock::Clock;
148    /// # use embedded_timers::instant::Instant32;
149    /// # fn sleep(_duration: Duration) {}
150    /// # struct MyClock;
151    /// # impl embedded_timers::clock::Clock for MyClock {
152    /// #     type Instant = Instant32<1000>;
153    /// #     fn now(&self) -> Instant32<1000> {
154    /// #         Instant32::new(0)
155    /// #     }
156    /// # }
157    ///
158    /// let clock = MyClock;
159    /// let now = clock.now();
160    /// sleep(Duration::new(1, 0));
161    /// let new_now = clock.now();
162    /// println!("{:?}", new_now.saturating_duration_since(now));
163    /// println!("{:?}", now.saturating_duration_since(new_now)); // 0ns
164    /// ```
165    #[must_use]
166    fn saturating_duration_since(&self, earlier: Self) -> Duration {
167        self.checked_duration_since(earlier).unwrap_or_default()
168    }
169
170    /// Returns `Some(t)` where `t` is the time `self + duration` if `t` can be represented as
171    /// `Self` (which means it's inside the bounds of the underlying data structure), `None`
172    /// otherwise.
173    fn checked_add(&self, duration: Duration) -> Option<Self>;
174
175    /// Returns `Some(t)` where `t` is the time `self - duration` if `t` can be represented as
176    /// `Instant` (which means it's inside the bounds of the underlying data structure), `None`
177    /// otherwise.
178    fn checked_sub(&self, duration: Duration) -> Option<Self>;
179}
180
181/// An `Instant` type inspired by the `timespec` struct from the C standard library
182///
183/// This instant type is implemented in a similar way as the [`Duration`] type because they both
184/// use a struct of seconds and (subsecond) nanoseconds to represent time. This has the great
185/// benefit that additions and subtractions do not require divisions, see the documentation to
186/// [`Instant32`] and [`Instant64`].
187///
188/// The main drawback of this instant type might be that creating these instants is harder. It can
189/// be done in basically two ways:
190/// 1. The underlying clock uses a simple integer tick counter. In these cases, creating each
191///    instant requires the division which is saved when working with the instants. Depending on
192///    the use case, this might be more or less efficient than using [`Instant32`] or [`Instant64`].
193/// 2. The underlying clock works on a similar seconds+nanoseconds struct directly. In these cases,
194///    creating an instant is easy but incrementing the underlying value in the clock tick
195///    interrupt gets harder. It is harder because the clock tick interrupt handler needs to take
196///    care of the nanosecond overflow which happens once per second and which needs to be properly
197///    synchronized with the contexts which request instants. Note though, that this might be the
198///    same problem as implementing a clock for [`Instant32`] or [`Instant64`] on platforms that do
199///    not support the corresponding atomic types. Especially on widespread 32 bit platforms, the
200///    [`AtomicU64`](https://doc.rust-lang.org/core/sync/atomic/struct.AtomicU64.html) might be
201///    missing.
202///
203/// Also, if you are especially concerned about data sizes, [`Instant32`] might be more appropriate
204/// for you because this type uses a 64 bit representation, see below.
205///
206/// The seconds and nanoseconds are both stored as `u32` values. For the nanoseconds, this should
207/// be obvious. For the seconds, using a 32 bit integer might remind of the [`year 2038
208/// problem`](https://en.wikipedia.org/wiki/Year_2038_problem) but this is only relevant when
209/// working with wall clock times. Since `Instant` is about working with monotonic clocks which can
210/// always be measured since program or system start, this would only be relevant if the program or
211/// system was designed to run for longer than about 136 years. So this should affect nearly no
212/// users at all. Therefore, saving additional bits seems reasonable.
213#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
214pub struct TimespecInstant {
215    secs: u32,
216    nanos: u32,
217}
218
219impl TimespecInstant {
220    /// Create a new TimespecInstant
221    pub fn new(secs: u32, nanos: u32) -> Self {
222        Self { secs, nanos }
223    }
224}
225
226impl Instant for TimespecInstant {
227    fn checked_duration_since(&self, earlier: Self) -> Option<Duration> {
228        let slf = Duration::new(self.secs as u64, self.nanos);
229        let early = Duration::new(earlier.secs as u64, earlier.nanos);
230        slf.checked_sub(early)
231    }
232
233    fn checked_add(&self, duration: Duration) -> Option<Self> {
234        let sum = Duration::new(self.secs as u64, self.nanos).checked_add(duration)?;
235        Some(TimespecInstant {
236            secs: sum.as_secs().try_into().ok()?,
237            nanos: sum.subsec_nanos(),
238        })
239    }
240
241    fn checked_sub(&self, duration: Duration) -> Option<Self> {
242        let diff = Duration::new(self.secs as u64, self.nanos).checked_add(duration)?;
243        Some(TimespecInstant {
244            secs: diff.as_secs().try_into().ok()?,
245            nanos: diff.subsec_nanos(),
246        })
247    }
248}
249
250impl core::ops::Add<Duration> for TimespecInstant {
251    type Output = TimespecInstant;
252
253    /// # Panics
254    ///
255    /// This function may panic if the resulting point in time cannot be represented by the
256    /// underlying data structure. See [`Instant::checked_add`] for a version without panic.
257    fn add(self, other: Duration) -> TimespecInstant {
258        self.checked_add(other)
259            .expect("overflow when adding duration to instant")
260    }
261}
262
263impl core::ops::AddAssign<Duration> for TimespecInstant {
264    fn add_assign(&mut self, other: Duration) {
265        *self = *self + other;
266    }
267}
268
269impl core::ops::Sub<Duration> for TimespecInstant {
270    type Output = TimespecInstant;
271
272    fn sub(self, other: Duration) -> TimespecInstant {
273        self.checked_sub(other)
274            .expect("overflow when subtracting duration from instant")
275    }
276}
277
278impl core::ops::SubAssign<Duration> for TimespecInstant {
279    fn sub_assign(&mut self, other: Duration) {
280        *self = *self - other;
281    }
282}
283
284impl core::ops::Sub<TimespecInstant> for TimespecInstant {
285    type Output = Duration;
286
287    /// Returns the amount of time elapsed from another instant to this one, or zero duration if
288    /// that instant is later than this one.
289    ///
290    /// # Panics
291    ///
292    /// As in the current version of the Rust stdlib, this method saturates instead of panicking.
293    fn sub(self, other: TimespecInstant) -> Duration {
294        self.duration_since(other)
295    }
296}
297
298macro_rules! impl_instant {
299    ($instant_name:ident, $primitive_type:ident) => {
300        /// An `Instant` type using a single unsigned integer tick counter
301        ///
302        /// For this type, it might be easy to create these instants and to handle the underlying
303        /// clock value, especially if the corresponding atomic type is available, see the
304        /// documentation to [`TimespecInstant`].
305        ///
306        /// The main drawback might be that all additions and subtractions require divisions which
307        /// might be inefficient on some platforms (when using an integer type larger than the word
308        /// width of the processor):
309        /// 1. Subtracting two instants yields a [`Duration`] which is a struct of seconds and
310        ///    (subsecond) nanoseconds. So this requires division and modulo to convert the simple
311        ///    tick difference into a `Duration`.
312        /// 2. Adding/subtracting a `Duration` to/from an instant requires to convert the seconds
313        ///    and nanoseconds into the corresponding ticks. Converting the seconds only requires
314        ///    multiplication with `TICKS_PER_SEC`, but converting the nanoseconds requires
315        ///    division by `nanos_per_sec` (which is calculated internally). This division is only
316        ///    a 32 bit division though.
317        ///
318        /// This instant type is generic on the clock frequency `TICKS_PER_SEC`. For example, in
319        /// order to implement a millisecond clock, set `TICKS_PER_SEC` to 1000.
320        // TODO Check how the output from the derived Debug impl looks like and if a manual one is
321        // better
322        #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
323        pub struct $instant_name<const TICKS_PER_SEC: u32> {
324            ticks: $primitive_type,
325        }
326
327        impl<const TICKS_PER_SEC: u32> $instant_name<TICKS_PER_SEC> {
328            /// Create a new Instant from the given number of ticks
329            pub fn new(ticks: $primitive_type) -> Self {
330                Self { ticks }
331            }
332        }
333
334        impl<const TICKS_PER_SEC: u32> Instant for $instant_name<TICKS_PER_SEC> {
335            fn checked_duration_since(&self, earlier: Self) -> Option<Duration> {
336                let ticks: $primitive_type = self.ticks.checked_sub(earlier.ticks)?;
337                let secs: $primitive_type = ticks / TICKS_PER_SEC as $primitive_type;
338                let remaining: $primitive_type = ticks % TICKS_PER_SEC as $primitive_type;
339                let remaining: u32 = remaining
340                    .try_into()
341                    .expect("more than u32::MAX subsec ticks");
342                let nanos_per_tick: u32 = 1_000_000_000 / TICKS_PER_SEC;
343                let nanos = remaining * nanos_per_tick;
344                Some(Duration::new(secs.into(), nanos))
345            }
346
347            fn checked_add(&self, duration: Duration) -> Option<Self> {
348                let mut ticks: $primitive_type = self.ticks;
349                let secs: $primitive_type = duration.as_secs().try_into().ok()?;
350                let sec_ticks = secs.checked_mul(TICKS_PER_SEC.into())?;
351                ticks = ticks.checked_add(sec_ticks)?;
352                let nanos: u32 = duration.subsec_nanos();
353                let nanos_per_tick: u32 = 1_000_000_000 / TICKS_PER_SEC;
354                let nano_ticks: u32 = nanos / nanos_per_tick;
355                ticks = ticks.checked_add(nano_ticks.into())?;
356                Some($instant_name { ticks })
357            }
358
359            fn checked_sub(&self, duration: Duration) -> Option<Self> {
360                let mut ticks: $primitive_type = self.ticks;
361                let secs: $primitive_type = duration.as_secs().try_into().ok()?;
362                let sec_ticks = secs.checked_mul(TICKS_PER_SEC.into())?;
363                ticks = ticks.checked_sub(sec_ticks)?;
364                let nanos: u32 = duration.subsec_nanos();
365                let nanos_per_tick: u32 = 1_000_000_000 / TICKS_PER_SEC;
366                let nano_ticks: u32 = nanos / nanos_per_tick;
367                ticks = ticks.checked_sub(nano_ticks.into())?;
368                Some($instant_name { ticks })
369            }
370        }
371
372        impl<const TICKS_PER_SEC: u32> core::ops::Add<Duration> for $instant_name<TICKS_PER_SEC> {
373            type Output = $instant_name<TICKS_PER_SEC>;
374
375            /// # Panics
376            ///
377            /// This function may panic if the resulting point in time cannot be represented by the
378            /// underlying data structure. See [`Instant::checked_add`] for a version without panic.
379            fn add(self, other: Duration) -> $instant_name<TICKS_PER_SEC> {
380                self.checked_add(other)
381                    .expect("overflow when adding duration to instant")
382            }
383        }
384
385        impl<const TICKS_PER_SEC: u32> core::ops::AddAssign<Duration>
386            for $instant_name<TICKS_PER_SEC>
387        {
388            fn add_assign(&mut self, other: Duration) {
389                *self = *self + other;
390            }
391        }
392
393        impl<const TICKS_PER_SEC: u32> core::ops::Sub<Duration> for $instant_name<TICKS_PER_SEC> {
394            type Output = $instant_name<TICKS_PER_SEC>;
395
396            fn sub(self, other: Duration) -> $instant_name<TICKS_PER_SEC> {
397                self.checked_sub(other)
398                    .expect("overflow when subtracting duration from instant")
399            }
400        }
401
402        impl<const TICKS_PER_SEC: u32> core::ops::SubAssign<Duration>
403            for $instant_name<TICKS_PER_SEC>
404        {
405            fn sub_assign(&mut self, other: Duration) {
406                *self = *self - other;
407            }
408        }
409
410        impl<const TICKS_PER_SEC: u32> core::ops::Sub<$instant_name<TICKS_PER_SEC>>
411            for $instant_name<TICKS_PER_SEC>
412        {
413            type Output = Duration;
414
415            /// Returns the amount of time elapsed from another instant to this one, or zero
416            /// duration if that instant is later than this one.
417            ///
418            /// # Panics
419            ///
420            /// As in the current version of the Rust stdlib, this method saturates instead of
421            /// panicking.
422            fn sub(self, other: $instant_name<TICKS_PER_SEC>) -> Duration {
423                self.duration_since(other)
424            }
425        }
426    };
427}
428
429impl_instant!(Instant32, u32);
430impl_instant!(Instant64, u64);
431
432#[cfg(feature = "std")]
433impl Instant for std::time::Instant {
434    fn checked_duration_since(&self, earlier: Self) -> Option<Duration> {
435        self.checked_duration_since(earlier)
436    }
437
438    fn checked_add(&self, duration: Duration) -> Option<Self> {
439        self.checked_add(duration)
440    }
441
442    fn checked_sub(&self, duration: Duration) -> Option<Self> {
443        self.checked_sub(duration)
444    }
445}