Skip to main content

fuchsia_async/runtime/fuchsia/executor/
time.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use super::common::EHandle;
6use crate::runtime::DurationExt;
7
8use std::ops;
9
10/// A time relative to the executor's clock.
11///
12/// # Panics
13///
14/// If there is no executor set up. For example if used in a context that is not
15/// bound to an executor, calling `now()` would panic.
16#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
17#[repr(transparent)]
18pub struct MonotonicInstant(zx::MonotonicInstant);
19
20pub use zx::MonotonicDuration;
21
22impl MonotonicInstant {
23    /// Return the current time according to the global executor.
24    ///
25    /// This function requires that an executor has been set up.
26    pub fn now() -> Self {
27        EHandle::local().inner().now()
28    }
29
30    /// Compute a deadline for the time in the future that is the
31    /// given `Duration` away. Similarly to `zx::MonotonicInstant::after`,
32    /// saturates on overflow instead of wrapping around.
33    ///
34    /// This function requires that an executor has been set up.
35    pub fn after(duration: zx::MonotonicDuration) -> Self {
36        Self::now() + duration
37    }
38
39    /// Convert from `zx::MonotonicInstant`.
40    pub const fn from_zx(t: zx::MonotonicInstant) -> Self {
41        MonotonicInstant(t)
42    }
43
44    /// Convert into `zx::MonotonicInstant`.
45    pub const fn into_zx(self) -> zx::MonotonicInstant {
46        self.0
47    }
48
49    /// Convert from nanoseconds.
50    pub const fn from_nanos(nanos: i64) -> Self {
51        Self::from_zx(zx::MonotonicInstant::from_nanos(nanos))
52    }
53
54    /// Convert to nanoseconds.
55    pub const fn into_nanos(self) -> i64 {
56        self.0.into_nanos()
57    }
58
59    /// The maximum time.
60    pub const INFINITE: MonotonicInstant = MonotonicInstant(zx::MonotonicInstant::INFINITE);
61
62    /// The minimum time.
63    pub const INFINITE_PAST: MonotonicInstant =
64        MonotonicInstant(zx::MonotonicInstant::INFINITE_PAST);
65
66    /// The epoch.
67    pub const ZERO: MonotonicInstant = MonotonicInstant(zx::MonotonicInstant::ZERO);
68}
69
70impl From<zx::MonotonicInstant> for MonotonicInstant {
71    fn from(t: zx::MonotonicInstant) -> MonotonicInstant {
72        MonotonicInstant(t)
73    }
74}
75
76impl From<MonotonicInstant> for zx::MonotonicInstant {
77    fn from(t: MonotonicInstant) -> zx::MonotonicInstant {
78        t.0
79    }
80}
81
82impl ops::Add<zx::MonotonicDuration> for MonotonicInstant {
83    type Output = MonotonicInstant;
84    fn add(self, d: zx::MonotonicDuration) -> MonotonicInstant {
85        MonotonicInstant(self.0 + d)
86    }
87}
88
89impl ops::Add<MonotonicInstant> for zx::MonotonicDuration {
90    type Output = MonotonicInstant;
91    fn add(self, t: MonotonicInstant) -> MonotonicInstant {
92        MonotonicInstant(self + t.0)
93    }
94}
95
96impl ops::Sub<zx::MonotonicDuration> for MonotonicInstant {
97    type Output = MonotonicInstant;
98    fn sub(self, d: zx::MonotonicDuration) -> MonotonicInstant {
99        MonotonicInstant(self.0 - d)
100    }
101}
102
103impl ops::Sub<MonotonicInstant> for MonotonicInstant {
104    type Output = zx::MonotonicDuration;
105    fn sub(self, t: MonotonicInstant) -> zx::MonotonicDuration {
106        self.0 - t.0
107    }
108}
109
110impl ops::AddAssign<zx::MonotonicDuration> for MonotonicInstant {
111    fn add_assign(&mut self, d: zx::MonotonicDuration) {
112        self.0.add_assign(d)
113    }
114}
115
116impl ops::SubAssign<zx::MonotonicDuration> for MonotonicInstant {
117    fn sub_assign(&mut self, d: zx::MonotonicDuration) {
118        self.0.sub_assign(d)
119    }
120}
121
122impl DurationExt for zx::MonotonicDuration {
123    fn after_now(self) -> MonotonicInstant {
124        MonotonicInstant::after(self)
125    }
126}
127
128/// A time relative to the executor's clock on the boot timeline.
129///
130/// # Panics
131///
132/// If there is no executor set up. For example if used in a context that is not
133/// bound to an executor, calling `now()` would panic.
134#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
135#[repr(transparent)]
136pub struct BootInstant(zx::BootInstant);
137
138impl BootInstant {
139    /// Return the current time according to the system boot clock. Advances while the system
140    /// is suspended.
141    pub fn now() -> Self {
142        EHandle::local().inner().boot_now()
143    }
144
145    /// Compute a deadline for the time in the future that is the
146    /// given `Duration` away. Similar to `zx::BootInstant::after`,
147    /// saturates on overflow instead of wrapping around.
148    pub fn after(duration: zx::BootDuration) -> Self {
149        Self::now() + duration
150    }
151
152    /// Convert from `zx::BootInstant`.
153    pub const fn from_zx(t: zx::BootInstant) -> Self {
154        BootInstant(t)
155    }
156
157    /// Convert into `zx::BootInstant`.
158    pub const fn into_zx(self) -> zx::BootInstant {
159        self.0
160    }
161
162    /// Convert from nanoseconds.
163    pub const fn from_nanos(nanos: i64) -> Self {
164        Self::from_zx(zx::BootInstant::from_nanos(nanos))
165    }
166
167    /// Convert to nanoseconds.
168    pub const fn into_nanos(self) -> i64 {
169        self.0.into_nanos()
170    }
171
172    /// The maximum time.
173    pub const INFINITE: BootInstant = BootInstant(zx::BootInstant::INFINITE);
174
175    /// The minimum time.
176    pub const INFINITE_PAST: BootInstant = BootInstant(zx::BootInstant::INFINITE_PAST);
177}
178
179impl From<zx::BootInstant> for BootInstant {
180    fn from(t: zx::BootInstant) -> BootInstant {
181        BootInstant(t)
182    }
183}
184
185impl From<BootInstant> for zx::BootInstant {
186    fn from(t: BootInstant) -> zx::BootInstant {
187        t.0
188    }
189}
190
191impl ops::Add<zx::BootDuration> for BootInstant {
192    type Output = BootInstant;
193    fn add(self, d: zx::BootDuration) -> BootInstant {
194        BootInstant(self.0 + d)
195    }
196}
197
198impl ops::Add<BootInstant> for zx::BootDuration {
199    type Output = BootInstant;
200    fn add(self, t: BootInstant) -> BootInstant {
201        BootInstant(self + t.0)
202    }
203}
204
205impl ops::Sub<zx::BootDuration> for BootInstant {
206    type Output = BootInstant;
207    fn sub(self, d: zx::BootDuration) -> BootInstant {
208        BootInstant(self.0 - d)
209    }
210}
211
212impl ops::Sub<BootInstant> for BootInstant {
213    type Output = zx::BootDuration;
214    fn sub(self, t: BootInstant) -> zx::BootDuration {
215        self.0 - t.0
216    }
217}
218
219impl ops::AddAssign<zx::BootDuration> for BootInstant {
220    fn add_assign(&mut self, d: zx::BootDuration) {
221        self.0.add_assign(d)
222    }
223}
224
225impl ops::SubAssign<zx::BootDuration> for BootInstant {
226    fn sub_assign(&mut self, d: zx::BootDuration) {
227        self.0.sub_assign(d)
228    }
229}
230
231#[cfg(test)]
232mod tests {
233    use super::*;
234
235    fn time_operations_param(
236        zxt1: zx::MonotonicInstant,
237        zxt2: zx::MonotonicInstant,
238        d: zx::MonotonicDuration,
239    ) {
240        let t1 = MonotonicInstant::from_zx(zxt1);
241        let t2 = MonotonicInstant::from_zx(zxt2);
242        assert_eq!(t1.into_zx(), zxt1);
243
244        assert_eq!(
245            MonotonicInstant::from_zx(zx::MonotonicInstant::INFINITE),
246            MonotonicInstant::INFINITE
247        );
248        assert_eq!(
249            MonotonicInstant::from_zx(zx::MonotonicInstant::INFINITE_PAST),
250            MonotonicInstant::INFINITE_PAST
251        );
252        assert_eq!(zxt1 - zxt2, t1 - t2);
253        assert_eq!(zxt1 + d, (t1 + d).into_zx());
254        assert_eq!(d + zxt1, (d + t1).into_zx());
255        assert_eq!(zxt1 - d, (t1 - d).into_zx());
256
257        let mut zxt = zxt1;
258        let mut t = t1;
259        t += d;
260        zxt += d;
261        assert_eq!(zxt, t.into_zx());
262        t -= d;
263        zxt -= d;
264        assert_eq!(zxt, t.into_zx());
265    }
266
267    #[test]
268    fn time_operations() {
269        time_operations_param(
270            zx::MonotonicInstant::from_nanos(0),
271            zx::MonotonicInstant::from_nanos(1000),
272            zx::MonotonicDuration::from_seconds(12),
273        );
274        time_operations_param(
275            zx::MonotonicInstant::from_nanos(-100000),
276            zx::MonotonicInstant::from_nanos(65324),
277            zx::MonotonicDuration::from_hours(-785),
278        );
279    }
280
281    #[test]
282    fn time_saturating_add() {
283        assert_eq!(
284            MonotonicInstant::from_nanos(10) + zx::MonotonicDuration::from_nanos(30),
285            MonotonicInstant::from_nanos(40)
286        );
287        assert_eq!(
288            MonotonicInstant::from_nanos(10)
289                + zx::MonotonicDuration::from_nanos(MonotonicInstant::INFINITE.into_nanos()),
290            MonotonicInstant::INFINITE
291        );
292        assert_eq!(
293            MonotonicInstant::from_nanos(-10)
294                + zx::MonotonicDuration::from_nanos(MonotonicInstant::INFINITE_PAST.into_nanos()),
295            MonotonicInstant::INFINITE_PAST
296        );
297    }
298}