about summary refs log tree commit diff
path: root/src/libstd/sys/windows
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-04-28 11:40:04 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-05-13 17:50:58 -0700
commit556e76bb78cdd1d951e3966b2264ef8567371881 (patch)
tree2b024aea65f5b77452414fd82a70150b956613c3 /src/libstd/sys/windows
parent05d5fcaa5ba0c385e1dc97037c89fae437634fc3 (diff)
downloadrust-556e76bb78cdd1d951e3966b2264ef8567371881.tar.gz
rust-556e76bb78cdd1d951e3966b2264ef8567371881.zip
std: Redesign Duration, implementing RFC 1040
This commit is an implementation of [RFC 1040][rfc] which is a redesign of the
currently-unstable `Duration` type. The API of the type has been scaled back to
be more conservative and it also no longer supports negative durations.

[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1040-duration-reform.md

The inner `duration` module of the `time` module has now been hidden (as
`Duration` is reexported) and the feature name for this type has changed from
`std_misc` to `duration`. All APIs accepting durations have also been audited to
take a more flavorful feature name instead of `std_misc`.

Closes #24874
Diffstat (limited to 'src/libstd/sys/windows')
-rw-r--r--src/libstd/sys/windows/condvar.rs2
-rw-r--r--src/libstd/sys/windows/mod.rs22
-rw-r--r--src/libstd/sys/windows/thread.rs10
-rw-r--r--src/libstd/sys/windows/time.rs20
4 files changed, 31 insertions, 23 deletions
diff --git a/src/libstd/sys/windows/condvar.rs b/src/libstd/sys/windows/condvar.rs
index 67552255fdb..8bb2326e4d6 100644
--- a/src/libstd/sys/windows/condvar.rs
+++ b/src/libstd/sys/windows/condvar.rs
@@ -42,7 +42,7 @@ impl Condvar {
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
         let r = ffi::SleepConditionVariableSRW(self.inner.get(),
                                                mutex::raw(mutex),
-                                               dur.num_milliseconds() as DWORD,
+                                               super::dur2timeout(dur),
                                                0);
         if r == 0 {
             const ERROR_TIMEOUT: DWORD = 0x5B4;
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index 5ae5f6f201b..d7a3a03de6d 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -20,6 +20,7 @@ use libc;
 use num::Zero;
 use os::windows::ffi::{OsStrExt, OsStringExt};
 use path::PathBuf;
+use time::Duration;
 
 pub mod backtrace;
 pub mod c;
@@ -151,6 +152,27 @@ fn cvt<I: PartialEq + Zero>(i: I) -> io::Result<I> {
     }
 }
 
+fn dur2timeout(dur: Duration) -> libc::DWORD {
+    // Note that a duration is a (u64, u32) (seconds, nanoseconds) pair, and the
+    // timeouts in windows APIs are typically u32 milliseconds. To translate, we
+    // have two pieces to take care of:
+    //
+    // * Nanosecond precision is rounded up
+    // * Greater than u32::MAX milliseconds (50 days) is rounded up to INFINITE
+    //   (never time out).
+    dur.secs().checked_mul(1000).and_then(|ms| {
+        ms.checked_add((dur.extra_nanos() as u64) / 1_000_000)
+    }).and_then(|ms| {
+        ms.checked_add(if dur.extra_nanos() % 1_000_000 > 0 {1} else {0})
+    }).map(|ms| {
+        if ms > <libc::DWORD>::max_value() as u64 {
+            libc::INFINITE
+        } else {
+            ms as libc::DWORD
+        }
+    }).unwrap_or(libc::INFINITE)
+}
+
 fn ms_to_filetime(ms: u64) -> libc::FILETIME {
     // A FILETIME is a count of 100 nanosecond intervals, so we multiply by
     // 10000 b/c there are 10000 intervals in 1 ms
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
index 797f45f8702..50dfee4ab10 100644
--- a/src/libstd/sys/windows/thread.rs
+++ b/src/libstd/sys/windows/thread.rs
@@ -80,15 +80,7 @@ impl Thread {
 
     pub fn sleep(dur: Duration) {
         unsafe {
-            if dur < Duration::zero() {
-                return Thread::yield_now()
-            }
-            let ms = dur.num_milliseconds();
-            // if we have a fractional number of milliseconds then add an extra
-            // millisecond to sleep for
-            let extra = dur - Duration::milliseconds(ms);
-            let ms = ms + if extra.is_zero() {0} else {1};
-            c::Sleep(ms as DWORD);
+            c::Sleep(super::dur2timeout(dur))
         }
     }
 }
diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs
index 209460df10b..e64df54a0fa 100644
--- a/src/libstd/sys/windows/time.rs
+++ b/src/libstd/sys/windows/time.rs
@@ -12,7 +12,7 @@ use ops::Sub;
 use time::Duration;
 use sync::{Once, ONCE_INIT};
 
-const NANOS_PER_SEC: i64 = 1_000_000_000;
+const NANOS_PER_SEC: u64 = 1_000_000_000;
 
 pub struct SteadyTime {
     t: libc::LARGE_INTEGER,
@@ -24,10 +24,6 @@ impl SteadyTime {
         unsafe { libc::QueryPerformanceCounter(&mut t.t); }
         t
     }
-
-    pub fn ns(&self) -> u64 {
-        mul_div_i64(self.t as i64, NANOS_PER_SEC, frequency() as i64) as u64
-    }
 }
 
 fn frequency() -> libc::LARGE_INTEGER {
@@ -46,15 +42,16 @@ impl<'a> Sub for &'a SteadyTime {
     type Output = Duration;
 
     fn sub(self, other: &SteadyTime) -> Duration {
-        let diff = self.t as i64 - other.t as i64;
-        Duration::nanoseconds(mul_div_i64(diff, NANOS_PER_SEC, frequency() as i64))
+        let diff = self.t as u64 - other.t as u64;
+        let nanos = mul_div_u64(diff, NANOS_PER_SEC, frequency() as u64);
+        Duration::new(nanos / NANOS_PER_SEC, (nanos % NANOS_PER_SEC) as u32)
     }
 }
 
 // Computes (value*numer)/denom without overflow, as long as both
 // (numer*denom) and the overall result fit into i64 (which is the case
 // for our time conversions).
-fn mul_div_i64(value: i64, numer: i64, denom: i64) -> i64 {
+fn mul_div_u64(value: u64, numer: u64, denom: u64) -> u64 {
     let q = value / denom;
     let r = value % denom;
     // Decompose value as (value/denom*denom + value%denom),
@@ -65,9 +62,6 @@ fn mul_div_i64(value: i64, numer: i64, denom: i64) -> i64 {
 
 #[test]
 fn test_muldiv() {
-    assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000, 1_000_000),  1_000_000_000_001_000);
-    assert_eq!(mul_div_i64(-1_000_000_000_001, 1_000_000_000, 1_000_000), -1_000_000_000_001_000);
-    assert_eq!(mul_div_i64(-1_000_000_000_001,-1_000_000_000, 1_000_000),  1_000_000_000_001_000);
-    assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000,-1_000_000), -1_000_000_000_001_000);
-    assert_eq!(mul_div_i64( 1_000_000_000_001,-1_000_000_000,-1_000_000),  1_000_000_000_001_000);
+    assert_eq!(mul_div_u64( 1_000_000_000_001, 1_000_000_000, 1_000_000),
+               1_000_000_000_001_000);
 }