]> git.proxmox.com Git - rustc.git/blob - src/libstd/sys/windows/time.rs
Imported Upstream version 1.2.0+dfsg1
[rustc.git] / src / libstd / sys / windows / time.rs
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 use libc;
11 use ops::Sub;
12 use time::Duration;
13 use sync::Once;
14
15 const NANOS_PER_SEC: u64 = 1_000_000_000;
16
17 pub struct SteadyTime {
18 t: libc::LARGE_INTEGER,
19 }
20
21 impl SteadyTime {
22 pub fn now() -> SteadyTime {
23 let mut t = SteadyTime { t: 0 };
24 unsafe { libc::QueryPerformanceCounter(&mut t.t); }
25 t
26 }
27 }
28
29 fn frequency() -> libc::LARGE_INTEGER {
30 static mut FREQUENCY: libc::LARGE_INTEGER = 0;
31 static ONCE: Once = Once::new();
32
33 unsafe {
34 ONCE.call_once(|| {
35 libc::QueryPerformanceFrequency(&mut FREQUENCY);
36 });
37 FREQUENCY
38 }
39 }
40
41 impl<'a> Sub for &'a SteadyTime {
42 type Output = Duration;
43
44 fn sub(self, other: &SteadyTime) -> Duration {
45 let diff = self.t as u64 - other.t as u64;
46 let nanos = mul_div_u64(diff, NANOS_PER_SEC, frequency() as u64);
47 Duration::new(nanos / NANOS_PER_SEC, (nanos % NANOS_PER_SEC) as u32)
48 }
49 }
50
51 // Computes (value*numer)/denom without overflow, as long as both
52 // (numer*denom) and the overall result fit into i64 (which is the case
53 // for our time conversions).
54 fn mul_div_u64(value: u64, numer: u64, denom: u64) -> u64 {
55 let q = value / denom;
56 let r = value % denom;
57 // Decompose value as (value/denom*denom + value%denom),
58 // substitute into (value*numer)/denom and simplify.
59 // r < denom, so (denom*numer) is the upper bound of (r*numer)
60 q * numer + r * numer / denom
61 }
62
63 #[test]
64 fn test_muldiv() {
65 assert_eq!(mul_div_u64( 1_000_000_000_001, 1_000_000_000, 1_000_000),
66 1_000_000_000_001_000);
67 }