Skip to content

Commit b289892

Browse files
committed
Auto merge of #29894 - alexcrichton:stdtime, r=brson
This commit is an implementation of [RFC 1288][rfc] which adds two new unstable types to the `std::time` module. The `Instant` type is used to represent measurements of a monotonically increasing clock suitable for measuring time withing a process for operations such as benchmarks or just the elapsed time to do something. An `Instant` favors panicking when bugs are found as the bugs are programmer errors rather than typical errors that can be encountered. [rfc]: rust-lang/rfcs#1288 The `SystemTime` type is used to represent a system timestamp and is not monotonic. Very few guarantees are provided about this measurement of the system clock, but a fixed point in time (`UNIX_EPOCH`) is provided to learn about the relative distance from this point for any particular time stamp. This PR takes the same implementation strategy as the `time` crate on crates.io, namely: | Platform | Instant | SystemTime | |------------|--------------------------|--------------------------| | Windows | QueryPerformanceCounter | GetSystemTimeAsFileTime | | OSX | mach_absolute_time | gettimeofday | | Unix | CLOCK_MONOTONIC | CLOCK_REALTIME | These implementations can perhaps be refined over time, but they currently satisfy the requirements of the `Instant` and `SystemTime` types while also being portable across implementations and revisions of each platform. cc #29866
2 parents 6861c51 + c6eb852 commit b289892

File tree

8 files changed

+816
-102
lines changed

8 files changed

+816
-102
lines changed

src/libstd/sync/condvar.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,10 @@ use prelude::v1::*;
1212

1313
use sync::atomic::{AtomicUsize, Ordering};
1414
use sync::{mutex, MutexGuard, PoisonError};
15-
use sys::time::SteadyTime;
1615
use sys_common::condvar as sys;
1716
use sys_common::mutex as sys_mutex;
1817
use sys_common::poison::{self, LockResult};
19-
use time::Duration;
18+
use time::{Instant, Duration};
2019

2120
/// A type indicating whether a timed wait on a condition variable returned
2221
/// due to a time out or not.
@@ -345,14 +344,13 @@ impl StaticCondvar {
345344
where F: FnMut(LockResult<&mut T>) -> bool {
346345
// This could be made more efficient by pushing the implementation into
347346
// sys::condvar
348-
let start = SteadyTime::now();
347+
let start = Instant::now();
349348
let mut guard_result: LockResult<MutexGuard<'a, T>> = Ok(guard);
350349
while !f(guard_result
351350
.as_mut()
352351
.map(|g| &mut **g)
353352
.map_err(|e| PoisonError::new(&mut **e.get_mut()))) {
354-
let now = SteadyTime::now();
355-
let consumed = &now - &start;
353+
let consumed = start.elapsed();
356354
let guard = guard_result.unwrap_or_else(|e| e.into_inner());
357355
let (new_guard_result, timed_out) = if consumed > dur {
358356
(Ok(guard), WaitTimeoutResult(true))

src/libstd/sys/common/mod.rs

+19
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,22 @@ pub fn cleanup() {
9898
at_exit_imp::cleanup();
9999
});
100100
}
101+
102+
// Computes (value*numer)/denom without overflow, as long as both
103+
// (numer*denom) and the overall result fit into i64 (which is the case
104+
// for our time conversions).
105+
#[allow(dead_code)] // not used on all platforms
106+
pub fn mul_div_u64(value: u64, numer: u64, denom: u64) -> u64 {
107+
let q = value / denom;
108+
let r = value % denom;
109+
// Decompose value as (value/denom*denom + value%denom),
110+
// substitute into (value*numer)/denom and simplify.
111+
// r < denom, so (denom*numer) is the upper bound of (r*numer)
112+
q * numer + r * numer / denom
113+
}
114+
115+
#[test]
116+
fn test_muldiv() {
117+
assert_eq!(mul_div_u64( 1_000_000_000_001, 1_000_000_000, 1_000_000),
118+
1_000_000_000_001_000);
119+
}

src/libstd/sys/unix/condvar.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ use cell::UnsafeCell;
1212
use libc;
1313
use ptr;
1414
use sys::mutex::{self, Mutex};
15-
use sys::time;
16-
use time::Duration;
15+
use time::{Instant, Duration};
1716

1817
pub struct Condvar { inner: UnsafeCell<libc::pthread_cond_t> }
1918

@@ -53,7 +52,7 @@ impl Condvar {
5352
// stable time. pthread_cond_timedwait uses system time, but we want to
5453
// report timeout based on stable time.
5554
let mut sys_now = libc::timeval { tv_sec: 0, tv_usec: 0 };
56-
let stable_now = time::SteadyTime::now();
55+
let stable_now = Instant::now();
5756
let r = libc::gettimeofday(&mut sys_now, ptr::null_mut());
5857
debug_assert_eq!(r, 0);
5958

@@ -81,7 +80,7 @@ impl Condvar {
8180

8281
// ETIMEDOUT is not a totally reliable method of determining timeout due
8382
// to clock shifts, so do the check ourselves
84-
&time::SteadyTime::now() - &stable_now < dur
83+
stable_now.elapsed() < dur
8584
}
8685

8786
#[inline]

0 commit comments

Comments
 (0)