]> git.proxmox.com Git - rustc.git/blame - src/libstd/sys/unix/time.rs
Imported Upstream version 1.6.0+dfsg1
[rustc.git] / src / libstd / sys / unix / time.rs
CommitLineData
85aaf69f
SL
1// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
92a42be0 11pub use self::inner::{Instant, SystemTime, UNIX_EPOCH};
85aaf69f 12
d9579d0f
AL
13const NSEC_PER_SEC: u64 = 1_000_000_000;
14
85aaf69f
SL
15#[cfg(any(target_os = "macos", target_os = "ios"))]
16mod inner {
92a42be0
SL
17 use cmp::Ordering;
18 use fmt;
85aaf69f 19 use libc;
d9579d0f 20 use super::NSEC_PER_SEC;
92a42be0
SL
21 use sync::Once;
22 use sys::cvt;
23 use sys_common::mul_div_u64;
24 use time::Duration;
85aaf69f 25
92a42be0
SL
26 const USEC_PER_SEC: u64 = NSEC_PER_SEC / 1000;
27
28 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
29 pub struct Instant {
85aaf69f
SL
30 t: u64
31 }
32
92a42be0
SL
33 #[derive(Copy, Clone)]
34 pub struct SystemTime {
35 t: libc::timeval,
85aaf69f
SL
36 }
37
92a42be0
SL
38 pub const UNIX_EPOCH: SystemTime = SystemTime {
39 t: libc::timeval {
40 tv_sec: 0,
41 tv_usec: 0,
42 },
43 };
44
45 impl Instant {
46 pub fn now() -> Instant {
47 Instant { t: unsafe { libc::mach_absolute_time() } }
48 }
49
50 pub fn sub_instant(&self, other: &Instant) -> Duration {
51 let info = info();
52 let diff = self.t.checked_sub(other.t)
53 .expect("second instant is later than self");
54 let nanos = mul_div_u64(diff, info.numer as u64, info.denom as u64);
55 Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32)
56 }
57
58 pub fn add_duration(&self, other: &Duration) -> Instant {
59 Instant {
60 t: self.t.checked_add(dur2intervals(other))
61 .expect("overflow when adding duration to instant"),
62 }
63 }
64
65 pub fn sub_duration(&self, other: &Duration) -> Instant {
66 Instant {
67 t: self.t.checked_sub(dur2intervals(other))
68 .expect("overflow when adding duration to instant"),
85aaf69f
SL
69 }
70 }
85aaf69f
SL
71 }
72
92a42be0
SL
73 impl SystemTime {
74 pub fn now() -> SystemTime {
75 let mut s = SystemTime {
76 t: libc::timeval {
77 tv_sec: 0,
78 tv_usec: 0,
79 },
80 };
81 cvt(unsafe {
82 libc::gettimeofday(&mut s.t, 0 as *mut _)
83 }).unwrap();
84 return s
85 }
86
87 pub fn sub_time(&self, other: &SystemTime)
88 -> Result<Duration, Duration> {
89 if self >= other {
90 Ok(if self.t.tv_usec >= other.t.tv_usec {
91 Duration::new(self.t.tv_sec as u64 - other.t.tv_sec as u64,
92 (self.t.tv_usec as u32 -
93 other.t.tv_usec as u32) * 1000)
94 } else {
95 Duration::new(self.t.tv_sec as u64 - 1 - other.t.tv_sec as u64,
96 (self.t.tv_usec as u32 + (USEC_PER_SEC as u32) -
97 other.t.tv_usec as u32) * 1000)
98 })
99 } else {
100 match other.sub_time(self) {
101 Ok(d) => Err(d),
102 Err(d) => Ok(d),
103 }
104 }
105 }
106
107 pub fn add_duration(&self, other: &Duration) -> SystemTime {
108 let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64);
109 let mut secs = secs.expect("overflow when adding duration to time");
110
111 // Nano calculations can't overflow because nanos are <1B which fit
112 // in a u32.
113 let mut usec = (other.subsec_nanos() / 1000) + self.t.tv_usec as u32;
114 if usec >= USEC_PER_SEC as u32 {
115 usec -= USEC_PER_SEC as u32;
116 secs = secs.checked_add(1).expect("overflow when adding \
117 duration to time");
118 }
119 SystemTime {
120 t: libc::timeval {
121 tv_sec: secs as libc::time_t,
122 tv_usec: usec as libc::suseconds_t,
123 },
124 }
125 }
126
127 pub fn sub_duration(&self, other: &Duration) -> SystemTime {
128 let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64);
129 let mut secs = secs.expect("overflow when subtracting duration \
130 from time");
131
132 // Similar to above, nanos can't overflow.
133 let mut usec = self.t.tv_usec as i32 -
134 (other.subsec_nanos() / 1000) as i32;
135 if usec < 0 {
136 usec += USEC_PER_SEC as i32;
137 secs = secs.checked_sub(1).expect("overflow when subtracting \
138 duration from time");
139 }
140 SystemTime {
141 t: libc::timeval {
142 tv_sec: secs as libc::time_t,
143 tv_usec: usec as libc::suseconds_t,
144 },
145 }
146 }
147 }
148
149 impl PartialEq for SystemTime {
150 fn eq(&self, other: &SystemTime) -> bool {
151 self.t.tv_sec == other.t.tv_sec && self.t.tv_usec == other.t.tv_usec
152 }
153 }
154
155 impl Eq for SystemTime {}
156
157 impl PartialOrd for SystemTime {
158 fn partial_cmp(&self, other: &SystemTime) -> Option<Ordering> {
159 Some(self.cmp(other))
160 }
161 }
162
163 impl Ord for SystemTime {
164 fn cmp(&self, other: &SystemTime) -> Ordering {
165 let me = (self.t.tv_sec, self.t.tv_usec);
166 let other = (other.t.tv_sec, other.t.tv_usec);
167 me.cmp(&other)
168 }
169 }
170
171 impl fmt::Debug for SystemTime {
172 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
173 f.debug_struct("SystemTime")
174 .field("tv_sec", &self.t.tv_sec)
175 .field("tv_usec", &self.t.tv_usec)
176 .finish()
177 }
178 }
179
180 fn dur2intervals(dur: &Duration) -> u64 {
181 let info = info();
182 let nanos = dur.as_secs().checked_mul(NSEC_PER_SEC).and_then(|nanos| {
183 nanos.checked_add(dur.subsec_nanos() as u64)
184 }).expect("overflow converting duration to nanoseconds");
185 mul_div_u64(nanos, info.denom as u64, info.numer as u64)
186 }
187
85aaf69f
SL
188 fn info() -> &'static libc::mach_timebase_info {
189 static mut INFO: libc::mach_timebase_info = libc::mach_timebase_info {
190 numer: 0,
191 denom: 0,
192 };
62682a34 193 static ONCE: Once = Once::new();
85aaf69f
SL
194
195 unsafe {
196 ONCE.call_once(|| {
92a42be0 197 libc::mach_timebase_info(&mut INFO);
85aaf69f
SL
198 });
199 &INFO
200 }
201 }
85aaf69f
SL
202}
203
204#[cfg(not(any(target_os = "macos", target_os = "ios")))]
205mod inner {
92a42be0
SL
206 use cmp::Ordering;
207 use fmt;
85aaf69f 208 use libc;
d9579d0f 209 use super::NSEC_PER_SEC;
92a42be0
SL
210 use sys::cvt;
211 use time::Duration;
85aaf69f 212
92a42be0
SL
213 #[derive(Copy, Clone)]
214 struct Timespec {
85aaf69f
SL
215 t: libc::timespec,
216 }
217
92a42be0
SL
218 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
219 pub struct Instant {
220 t: Timespec,
221 }
222
223 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
224 pub struct SystemTime {
225 t: Timespec,
226 }
227
228 pub const UNIX_EPOCH: SystemTime = SystemTime {
229 t: Timespec {
230 t: libc::timespec {
231 tv_sec: 0,
232 tv_nsec: 0,
233 },
234 },
235 };
85aaf69f 236
92a42be0
SL
237 impl Instant {
238 pub fn now() -> Instant {
239 Instant { t: Timespec::now(libc::CLOCK_MONOTONIC) }
240 }
241
242 pub fn sub_instant(&self, other: &Instant) -> Duration {
243 self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
244 panic!("other was less than the current instant")
245 })
246 }
247
248 pub fn add_duration(&self, other: &Duration) -> Instant {
249 Instant { t: self.t.add_duration(other) }
250 }
251
252 pub fn sub_duration(&self, other: &Duration) -> Instant {
253 Instant { t: self.t.sub_duration(other) }
254 }
255 }
256
257 impl fmt::Debug for Instant {
258 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
259 f.debug_struct("Instant")
260 .field("tv_sec", &self.t.t.tv_sec)
261 .field("tv_nsec", &self.t.t.tv_nsec)
262 .finish()
263 }
264 }
265
266 impl SystemTime {
267 pub fn now() -> SystemTime {
268 SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) }
269 }
270
271 pub fn sub_time(&self, other: &SystemTime)
272 -> Result<Duration, Duration> {
273 self.t.sub_timespec(&other.t)
274 }
275
276 pub fn add_duration(&self, other: &Duration) -> SystemTime {
277 SystemTime { t: self.t.add_duration(other) }
278 }
279
280 pub fn sub_duration(&self, other: &Duration) -> SystemTime {
281 SystemTime { t: self.t.sub_duration(other) }
282 }
283 }
b039eaaf 284
92a42be0
SL
285 impl fmt::Debug for SystemTime {
286 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
287 f.debug_struct("SystemTime")
288 .field("tv_sec", &self.t.t.tv_sec)
289 .field("tv_nsec", &self.t.t.tv_nsec)
290 .finish()
291 }
85aaf69f
SL
292 }
293
92a42be0
SL
294 impl Timespec {
295 pub fn now(clock: libc::c_int) -> Timespec {
296 let mut t = Timespec {
85aaf69f
SL
297 t: libc::timespec {
298 tv_sec: 0,
299 tv_nsec: 0,
300 }
301 };
92a42be0
SL
302 cvt(unsafe {
303 libc::clock_gettime(clock, &mut t.t)
304 }).unwrap();
85aaf69f
SL
305 t
306 }
85aaf69f 307
92a42be0
SL
308 fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
309 if self >= other {
310 Ok(if self.t.tv_nsec >= other.t.tv_nsec {
311 Duration::new((self.t.tv_sec - other.t.tv_sec) as u64,
312 (self.t.tv_nsec - other.t.tv_nsec) as u32)
313 } else {
314 Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64,
315 self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) -
316 other.t.tv_nsec as u32)
317 })
85aaf69f 318 } else {
92a42be0
SL
319 match other.sub_timespec(self) {
320 Ok(d) => Err(d),
321 Err(d) => Ok(d),
322 }
323 }
324 }
325
326 fn add_duration(&self, other: &Duration) -> Timespec {
327 let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64);
328 let mut secs = secs.expect("overflow when adding duration to time");
329
330 // Nano calculations can't overflow because nanos are <1B which fit
331 // in a u32.
332 let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
333 if nsec >= NSEC_PER_SEC as u32 {
334 nsec -= NSEC_PER_SEC as u32;
335 secs = secs.checked_add(1).expect("overflow when adding \
336 duration to time");
337 }
338 Timespec {
339 t: libc::timespec {
340 tv_sec: secs as libc::time_t,
341 tv_nsec: nsec as libc::c_long,
342 },
85aaf69f
SL
343 }
344 }
92a42be0
SL
345
346 fn sub_duration(&self, other: &Duration) -> Timespec {
347 let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64);
348 let mut secs = secs.expect("overflow when subtracting duration \
349 from time");
350
351 // Similar to above, nanos can't overflow.
352 let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
353 if nsec < 0 {
354 nsec += NSEC_PER_SEC as i32;
355 secs = secs.checked_sub(1).expect("overflow when subtracting \
356 duration from time");
357 }
358 Timespec {
359 t: libc::timespec {
360 tv_sec: secs as libc::time_t,
361 tv_nsec: nsec as libc::c_long,
362 },
363 }
364 }
365 }
366
367 impl PartialEq for Timespec {
368 fn eq(&self, other: &Timespec) -> bool {
369 self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec
370 }
371 }
372
373 impl Eq for Timespec {}
374
375 impl PartialOrd for Timespec {
376 fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> {
377 Some(self.cmp(other))
378 }
379 }
380
381 impl Ord for Timespec {
382 fn cmp(&self, other: &Timespec) -> Ordering {
383 let me = (self.t.tv_sec, self.t.tv_nsec);
384 let other = (other.t.tv_sec, other.t.tv_nsec);
385 me.cmp(&other)
386 }
85aaf69f
SL
387 }
388}