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}