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
67impl From<zx::MonotonicInstant> for MonotonicInstant {
68    fn from(t: zx::MonotonicInstant) -> MonotonicInstant {
69        MonotonicInstant(t)
70    }
71}
72
73impl From<MonotonicInstant> for zx::MonotonicInstant {
74    fn from(t: MonotonicInstant) -> zx::MonotonicInstant {
75        t.0
76    }
77}
78
79impl ops::Add<zx::MonotonicDuration> for MonotonicInstant {
80    type Output = MonotonicInstant;
81    fn add(self, d: zx::MonotonicDuration) -> MonotonicInstant {
82        MonotonicInstant(self.0 + d)
83    }
84}
85
86impl ops::Add<MonotonicInstant> for zx::MonotonicDuration {
87    type Output = MonotonicInstant;
88    fn add(self, t: MonotonicInstant) -> MonotonicInstant {
89        MonotonicInstant(self + t.0)
90    }
91}
92
93impl ops::Sub<zx::MonotonicDuration> for MonotonicInstant {
94    type Output = MonotonicInstant;
95    fn sub(self, d: zx::MonotonicDuration) -> MonotonicInstant {
96        MonotonicInstant(self.0 - d)
97    }
98}
99
100impl ops::Sub<MonotonicInstant> for MonotonicInstant {
101    type Output = zx::MonotonicDuration;
102    fn sub(self, t: MonotonicInstant) -> zx::MonotonicDuration {
103        self.0 - t.0
104    }
105}
106
107impl ops::AddAssign<zx::MonotonicDuration> for MonotonicInstant {
108    fn add_assign(&mut self, d: zx::MonotonicDuration) {
109        self.0.add_assign(d)
110    }
111}
112
113impl ops::SubAssign<zx::MonotonicDuration> for MonotonicInstant {
114    fn sub_assign(&mut self, d: zx::MonotonicDuration) {
115        self.0.sub_assign(d)
116    }
117}
118
119impl DurationExt for zx::MonotonicDuration {
120    fn after_now(self) -> MonotonicInstant {
121        MonotonicInstant::after(self)
122    }
123}
124
125/// A time relative to the executor's clock on the boot timeline.
126///
127/// # Panics
128///
129/// If there is no executor set up. For example if used in a context that is not
130/// bound to an executor, calling `now()` would panic.
131#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
132#[repr(transparent)]
133pub struct BootInstant(zx::BootInstant);
134
135impl BootInstant {
136    /// Return the current time according to the system boot clock. Advances while the system
137    /// is suspended.
138    pub fn now() -> Self {
139        EHandle::local().inner().boot_now()
140    }
141
142    /// Compute a deadline for the time in the future that is the
143    /// given `Duration` away. Similar to `zx::BootInstant::after`,
144    /// saturates on overflow instead of wrapping around.
145    pub fn after(duration: zx::BootDuration) -> Self {
146        Self::now() + duration
147    }
148
149    /// Convert from `zx::BootInstant`.
150    pub const fn from_zx(t: zx::BootInstant) -> Self {
151        BootInstant(t)
152    }
153
154    /// Convert into `zx::BootInstant`.
155    pub const fn into_zx(self) -> zx::BootInstant {
156        self.0
157    }
158
159    /// Convert from nanoseconds.
160    pub const fn from_nanos(nanos: i64) -> Self {
161        Self::from_zx(zx::BootInstant::from_nanos(nanos))
162    }
163
164    /// Convert to nanoseconds.
165    pub const fn into_nanos(self) -> i64 {
166        self.0.into_nanos()
167    }
168
169    /// The maximum time.
170    pub const INFINITE: BootInstant = BootInstant(zx::BootInstant::INFINITE);
171
172    /// The minimum time.
173    pub const INFINITE_PAST: BootInstant = BootInstant(zx::BootInstant::INFINITE_PAST);
174}
175
176impl From<zx::BootInstant> for BootInstant {
177    fn from(t: zx::BootInstant) -> BootInstant {
178        BootInstant(t)
179    }
180}
181
182impl From<BootInstant> for zx::BootInstant {
183    fn from(t: BootInstant) -> zx::BootInstant {
184        t.0
185    }
186}
187
188impl ops::Add<zx::BootDuration> for BootInstant {
189    type Output = BootInstant;
190    fn add(self, d: zx::BootDuration) -> BootInstant {
191        BootInstant(self.0 + d)
192    }
193}
194
195impl ops::Add<BootInstant> for zx::BootDuration {
196    type Output = BootInstant;
197    fn add(self, t: BootInstant) -> BootInstant {
198        BootInstant(self + t.0)
199    }
200}
201
202impl ops::Sub<zx::BootDuration> for BootInstant {
203    type Output = BootInstant;
204    fn sub(self, d: zx::BootDuration) -> BootInstant {
205        BootInstant(self.0 - d)
206    }
207}
208
209impl ops::Sub<BootInstant> for BootInstant {
210    type Output = zx::BootDuration;
211    fn sub(self, t: BootInstant) -> zx::BootDuration {
212        self.0 - t.0
213    }
214}
215
216impl ops::AddAssign<zx::BootDuration> for BootInstant {
217    fn add_assign(&mut self, d: zx::BootDuration) {
218        self.0.add_assign(d)
219    }
220}
221
222impl ops::SubAssign<zx::BootDuration> for BootInstant {
223    fn sub_assign(&mut self, d: zx::BootDuration) {
224        self.0.sub_assign(d)
225    }
226}
227
228#[cfg(test)]
229mod tests {
230    use super::*;
231
232    fn time_operations_param(
233        zxt1: zx::MonotonicInstant,
234        zxt2: zx::MonotonicInstant,
235        d: zx::MonotonicDuration,
236    ) {
237        let t1 = MonotonicInstant::from_zx(zxt1);
238        let t2 = MonotonicInstant::from_zx(zxt2);
239        assert_eq!(t1.into_zx(), zxt1);
240
241        assert_eq!(
242            MonotonicInstant::from_zx(zx::MonotonicInstant::INFINITE),
243            MonotonicInstant::INFINITE
244        );
245        assert_eq!(
246            MonotonicInstant::from_zx(zx::MonotonicInstant::INFINITE_PAST),
247            MonotonicInstant::INFINITE_PAST
248        );
249        assert_eq!(zxt1 - zxt2, t1 - t2);
250        assert_eq!(zxt1 + d, (t1 + d).into_zx());
251        assert_eq!(d + zxt1, (d + t1).into_zx());
252        assert_eq!(zxt1 - d, (t1 - d).into_zx());
253
254        let mut zxt = zxt1;
255        let mut t = t1;
256        t += d;
257        zxt += d;
258        assert_eq!(zxt, t.into_zx());
259        t -= d;
260        zxt -= d;
261        assert_eq!(zxt, t.into_zx());
262    }
263
264    #[test]
265    fn time_operations() {
266        time_operations_param(
267            zx::MonotonicInstant::from_nanos(0),
268            zx::MonotonicInstant::from_nanos(1000),
269            zx::MonotonicDuration::from_seconds(12),
270        );
271        time_operations_param(
272            zx::MonotonicInstant::from_nanos(-100000),
273            zx::MonotonicInstant::from_nanos(65324),
274            zx::MonotonicDuration::from_hours(-785),
275        );
276    }
277
278    #[test]
279    fn time_saturating_add() {
280        assert_eq!(
281            MonotonicInstant::from_nanos(10) + zx::MonotonicDuration::from_nanos(30),
282            MonotonicInstant::from_nanos(40)
283        );
284        assert_eq!(
285            MonotonicInstant::from_nanos(10)
286                + zx::MonotonicDuration::from_nanos(MonotonicInstant::INFINITE.into_nanos()),
287            MonotonicInstant::INFINITE
288        );
289        assert_eq!(
290            MonotonicInstant::from_nanos(-10)
291                + zx::MonotonicDuration::from_nanos(MonotonicInstant::INFINITE_PAST.into_nanos()),
292            MonotonicInstant::INFINITE_PAST
293        );
294    }
295}