s2n_quic_core/time/
clock.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::time::timestamp::Timestamp;
5use core::{
6    task::{Context, Poll},
7    time::Duration,
8};
9
10#[cfg(any(test, feature = "std"))]
11mod std;
12#[cfg(any(test, feature = "testing"))]
13pub mod testing;
14
15#[cfg(any(test, feature = "std"))]
16pub use self::std::*;
17
18/// A `Clock` is a source of [`Timestamp`]s.
19pub trait Clock {
20    /// Returns the current [`Timestamp`]
21    fn get_time(&self) -> Timestamp;
22}
23
24pub trait ClockWithTimer: Clock {
25    type Timer: Timer;
26
27    fn timer(&self) -> Self::Timer;
28}
29
30pub trait Timer {
31    #[inline]
32    fn ready(&mut self) -> TimerReady<Self> {
33        TimerReady(self)
34    }
35
36    fn poll_ready(&mut self, cx: &mut Context) -> Poll<()>;
37    fn update(&mut self, timestamp: Timestamp);
38}
39
40impl_ready_future!(Timer, TimerReady, ());
41
42/// A clock which always returns a Timestamp of value 1us
43#[derive(Clone, Copy, Debug, Default)]
44pub struct NoopClock;
45
46impl Clock for NoopClock {
47    fn get_time(&self) -> Timestamp {
48        unsafe { Timestamp::from_duration(Duration::from_micros(1)) }
49    }
50}
51
52impl Clock for Timestamp {
53    #[inline]
54    fn get_time(&self) -> Timestamp {
55        *self
56    }
57}
58
59/// A clock that caches the time query for the inner clock
60pub struct Cached<'a, C: Clock + ?Sized> {
61    clock: &'a C,
62    cached_value: core::cell::Cell<Option<Timestamp>>,
63}
64
65impl<'a, C: Clock + ?Sized> Cached<'a, C> {
66    #[inline]
67    pub fn new(clock: &'a C) -> Self {
68        Self {
69            clock,
70            cached_value: Default::default(),
71        }
72    }
73}
74
75impl<C: Clock + ?Sized> Clock for Cached<'_, C> {
76    #[inline]
77    fn get_time(&self) -> Timestamp {
78        if let Some(time) = self.cached_value.get() {
79            return time;
80        }
81
82        let now = self.clock.get_time();
83        self.cached_value.set(Some(now));
84        now
85    }
86}