1use {AsHandleRef, ClockId, HandleBased, Handle, HandleRef, Status};
8use {sys, ok};
9use std::ops;
10use std::time as stdtime;
11
12#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
13pub struct Duration(sys::zx_duration_t);
14
15#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
16pub struct Time(sys::zx_time_t);
17
18impl From<stdtime::Duration> for Duration {
19 fn from(dur: stdtime::Duration) -> Self {
20 Duration::from_seconds(dur.as_secs()) +
21 Duration::from_nanos(dur.subsec_nanos() as u64)
22 }
23}
24
25impl From<Duration> for stdtime::Duration {
26 fn from(dur: Duration) -> Self {
27 let secs = dur.seconds();
28 let nanos = (dur.nanos() - (secs * 1_000_000_000)) as u32;
29 stdtime::Duration::new(secs, nanos)
30 }
31}
32
33impl ops::Add<Duration> for Time {
34 type Output = Time;
35 fn add(self, dur: Duration) -> Time {
36 Time::from_nanos(dur.nanos() + self.nanos())
37 }
38}
39
40impl ops::Add<Time> for Duration {
41 type Output = Time;
42 fn add(self, time: Time) -> Time {
43 Time::from_nanos(self.nanos() + time.nanos())
44 }
45}
46
47impl ops::Add for Duration {
48 type Output = Duration;
49 fn add(self, dur: Duration) -> Duration {
50 Duration::from_nanos(self.nanos() + dur.nanos())
51 }
52}
53
54impl ops::Sub for Duration {
55 type Output = Duration;
56 fn sub(self, dur: Duration) -> Duration {
57 Duration::from_nanos(self.nanos() - dur.nanos())
58 }
59}
60
61impl ops::Sub<Duration> for Time {
62 type Output = Time;
63 fn sub(self, dur: Duration) -> Time {
64 Time::from_nanos(self.nanos() - dur.nanos())
65 }
66}
67
68impl ops::AddAssign for Duration {
69 fn add_assign(&mut self, dur: Duration) {
70 self.0 += dur.nanos()
71 }
72}
73
74impl ops::SubAssign for Duration {
75 fn sub_assign(&mut self, dur: Duration) {
76 self.0 -= dur.nanos()
77 }
78}
79
80impl ops::AddAssign<Duration> for Time {
81 fn add_assign(&mut self, dur: Duration) {
82 self.0 += dur.nanos()
83 }
84}
85
86impl ops::SubAssign<Duration> for Time {
87 fn sub_assign(&mut self, dur: Duration) {
88 self.0 -= dur.nanos()
89 }
90}
91
92impl<T> ops::Mul<T> for Duration
93 where T: Into<u64>
94{
95 type Output = Self;
96 fn mul(self, mul: T) -> Self {
97 Duration::from_nanos(self.0 * mul.into())
98 }
99}
100
101impl<T> ops::Div<T> for Duration
102 where T: Into<u64>
103{
104 type Output = Self;
105 fn div(self, div: T) -> Self {
106 Duration::from_nanos(self.0 / div.into())
107 }
108}
109
110impl Duration {
111 pub fn sleep(self) {
113 Time::after(self).sleep()
114 }
115
116 pub fn nanos(self) -> u64 {
117 self.0
118 }
119
120 pub fn millis(self) -> u64 {
121 self.0 / 1_000_000
122 }
123
124 pub fn seconds(self) -> u64 {
125 self.millis() / 1_000
126 }
127
128 pub fn minutes(self) -> u64 {
129 self.seconds() / 60
130 }
131
132 pub fn hours(self) -> u64 {
133 self.minutes() / 60
134 }
135
136 pub fn from_nanos(nanos: u64) -> Self {
137 Duration(nanos)
138 }
139
140 pub fn from_millis(millis: u64) -> Self {
141 Duration(millis * 1_000_000)
142 }
143
144 pub fn from_seconds(secs: u64) -> Self {
145 Duration::from_millis(secs * 1_000)
146 }
147
148 pub fn from_minutes(min: u64) -> Self {
149 Duration::from_seconds(min * 60)
150 }
151
152 pub fn from_hours(hours: u64) -> Self {
153 Duration::from_minutes(hours * 60)
154 }
155
156 pub fn after_now(self) -> Time {
159 Time::after(self)
160 }
161}
162
163pub trait DurationNum: Sized {
164 fn nanos(self) -> Duration;
165 fn millis(self) -> Duration;
166 fn seconds(self) -> Duration;
167 fn minutes(self) -> Duration;
168 fn hours(self) -> Duration;
169
170 fn milli(self) -> Duration { self.millis() }
172 fn second(self) -> Duration { self.seconds() }
173 fn minute(self) -> Duration { self.minutes() }
174 fn hour(self) -> Duration { self.hours() }
175}
176
177impl DurationNum for u64 {
180 fn nanos(self) -> Duration {
181 Duration::from_nanos(self)
182 }
183
184 fn millis(self) -> Duration {
185 Duration::from_millis(self)
186 }
187
188 fn seconds(self) -> Duration {
189 Duration::from_seconds(self)
190 }
191
192 fn minutes(self) -> Duration {
193 Duration::from_minutes(self)
194 }
195
196 fn hours(self) -> Duration {
197 Duration::from_hours(self)
198 }
199}
200
201impl Time {
202 pub const INFINITE: Time = Time(sys::ZX_TIME_INFINITE);
203
204 pub fn get(clock_id: ClockId) -> Time {
210 unsafe { Time(sys::zx_time_get(clock_id as u32)) }
211 }
212
213 pub fn after(duration: Duration) -> Time {
219 unsafe { Time(sys::zx_deadline_after(duration.0)) }
220 }
221
222 pub fn sleep(self) {
228 unsafe { sys::zx_nanosleep(self.0); }
229 }
230
231 pub fn nanos(self) -> u64 {
232 self.0
233 }
234
235 pub fn from_nanos(nanos: u64) -> Self {
236 Time(nanos)
237 }
238}
239
240pub fn ticks_get() -> u64 {
248 unsafe { sys::zx_ticks_get() }
249}
250
251pub fn ticks_per_second() -> u64 {
257 unsafe { sys::zx_ticks_per_second() }
258}
259
260#[derive(Debug, Eq, PartialEq)]
265pub struct Timer(Handle);
266impl_handle_based!(Timer);
267
268impl Timer {
269 pub fn create(clock_id: ClockId) -> Result<Timer, Status> {
274 let mut out = 0;
275 let opts = 0;
276 let status = unsafe { sys::zx_timer_create(opts, clock_id as u32, &mut out) };
277 ok(status)?;
278 unsafe {
279 Ok(Self::from(Handle::from_raw(out)))
280 }
281 }
282
283 pub fn set(&self, deadline: Time, slack: Duration) -> Result<(), Status> {
287 let status = unsafe {
288 sys::zx_timer_set(self.raw_handle(), deadline.nanos(), slack.nanos())
289 };
290 ok(status)
291 }
292
293 pub fn cancel(&self) -> Result<(), Status> {
297 let status = unsafe { sys::zx_timer_cancel(self.raw_handle()) };
298 ok(status)
299 }
300}
301
302#[cfg(test)]
303mod tests {
304 use super::*;
305 use Signals;
306
307 #[test]
308 fn create_timer_invalid_clock() {
309 assert_eq!(Timer::create(ClockId::UTC).unwrap_err(), Status::INVALID_ARGS);
310 assert_eq!(Timer::create(ClockId::Thread), Err(Status::INVALID_ARGS));
311 }
312
313 #[test]
314 fn into_from_std() {
315 let std_dur = stdtime::Duration::new(25, 25);
316 assert_eq!(std_dur, stdtime::Duration::from(Duration::from(std_dur)));
317 }
318
319 #[test]
320 fn timer_basic() {
321 let slack = 0.millis();
322 let ten_ms = 10.millis();
323 let five_secs = 5.seconds();
324 let six_secs = 6.seconds();
325
326 let timer = Timer::create(ClockId::Monotonic).unwrap();
328
329 assert_eq!(
331 timer.wait_handle(Signals::TIMER_SIGNALED, ten_ms.after_now()),
332 Err(Status::TIMED_OUT));
333
334 assert_eq!(timer.set(five_secs.after_now(), slack), Ok(()));
336 assert_eq!(
337 timer.wait_handle(Signals::TIMER_SIGNALED, six_secs.after_now()),
338 Ok(Signals::TIMER_SIGNALED));
339
340 assert_eq!(timer.cancel(), Ok(()));
342 assert_eq!(
343 timer.wait_handle(Signals::TIMER_SIGNALED, ten_ms.after_now()),
344 Err(Status::TIMED_OUT));
345 }
346}