mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
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
This commit is contained in:
parent
05d5fcaa5b
commit
556e76bb78
@ -30,6 +30,8 @@
|
||||
#![feature(box_syntax)]
|
||||
#![feature(collections)]
|
||||
#![feature(core)]
|
||||
#![feature(duration)]
|
||||
#![feature(duration_span)]
|
||||
#![feature(fs_canonicalize)]
|
||||
#![feature(hash)]
|
||||
#![feature(into_cow)]
|
||||
|
@ -720,8 +720,7 @@ fn get_metadata_section(is_osx: bool, filename: &Path) -> Result<MetadataBlob, S
|
||||
let dur = Duration::span(|| {
|
||||
ret = Some(get_metadata_section_imp(is_osx, filename));
|
||||
});
|
||||
info!("reading {:?} => {}ms", filename.file_name().unwrap(),
|
||||
dur.num_milliseconds());
|
||||
info!("reading {:?} => {}", filename.file_name().unwrap(), dur);
|
||||
return ret.unwrap();;
|
||||
}
|
||||
|
||||
|
@ -55,8 +55,8 @@ pub fn time<T, U, F>(do_it: bool, what: &str, u: U, f: F) -> T where
|
||||
};
|
||||
let rv = rv.unwrap();
|
||||
|
||||
println!("{}time: {}.{:03} \t{}", repeat(" ").take(old).collect::<String>(),
|
||||
dur.num_seconds(), dur.num_milliseconds() % 1000, what);
|
||||
println!("{}time: {} \t{}", repeat(" ").take(old).collect::<String>(),
|
||||
dur, what);
|
||||
DEPTH.with(|slot| slot.set(old));
|
||||
|
||||
rv
|
||||
|
@ -69,12 +69,12 @@ pub struct Condvar { inner: Box<StaticCondvar> }
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(std_misc)]
|
||||
/// # #![feature(static_condvar)]
|
||||
/// use std::sync::{StaticCondvar, CONDVAR_INIT};
|
||||
///
|
||||
/// static CVAR: StaticCondvar = CONDVAR_INIT;
|
||||
/// ```
|
||||
#[unstable(feature = "std_misc",
|
||||
#[unstable(feature = "static_condvar",
|
||||
reason = "may be merged with Condvar in the future")]
|
||||
pub struct StaticCondvar {
|
||||
inner: sys::Condvar,
|
||||
@ -82,7 +82,7 @@ pub struct StaticCondvar {
|
||||
}
|
||||
|
||||
/// Constant initializer for a statically allocated condition variable.
|
||||
#[unstable(feature = "std_misc",
|
||||
#[unstable(feature = "static_condvar",
|
||||
reason = "may be merged with Condvar in the future")]
|
||||
pub const CONDVAR_INIT: StaticCondvar = StaticCondvar {
|
||||
inner: sys::CONDVAR_INIT,
|
||||
@ -161,6 +161,30 @@ impl Condvar {
|
||||
}
|
||||
}
|
||||
|
||||
/// Waits on this condition variable for a notification, timing out after a
|
||||
/// specified duration.
|
||||
///
|
||||
/// The semantics of this function are equivalent to `wait()` except that
|
||||
/// the thread will be blocked for roughly no longer than `dur`. This
|
||||
/// method should not be used for precise timing due to anomalies such as
|
||||
/// preemption or platform differences that may not cause the maximum
|
||||
/// amount of time waited to be precisely `dur`.
|
||||
///
|
||||
/// The returned boolean is `false` only if the timeout is known
|
||||
/// to have elapsed.
|
||||
///
|
||||
/// Like `wait`, the lock specified will be re-acquired when this function
|
||||
/// returns, regardless of whether the timeout elapsed or not.
|
||||
#[unstable(feature = "wait_timeout", reason = "waiting for Duration")]
|
||||
pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>,
|
||||
dur: Duration)
|
||||
-> LockResult<(MutexGuard<'a, T>, bool)> {
|
||||
unsafe {
|
||||
let me: &'static Condvar = &*(self as *const _);
|
||||
me.inner.wait_timeout(guard, dur)
|
||||
}
|
||||
}
|
||||
|
||||
/// Waits on this condition variable for a notification, timing out after a
|
||||
/// specified duration.
|
||||
///
|
||||
@ -214,7 +238,7 @@ impl StaticCondvar {
|
||||
/// notification.
|
||||
///
|
||||
/// See `Condvar::wait`.
|
||||
#[unstable(feature = "std_misc",
|
||||
#[unstable(feature = "static_condvar",
|
||||
reason = "may be merged with Condvar in the future")]
|
||||
pub fn wait<'a, T>(&'static self, guard: MutexGuard<'a, T>)
|
||||
-> LockResult<MutexGuard<'a, T>> {
|
||||
@ -235,14 +259,27 @@ impl StaticCondvar {
|
||||
/// specified duration.
|
||||
///
|
||||
/// See `Condvar::wait_timeout`.
|
||||
#[unstable(feature = "std_misc",
|
||||
#[unstable(feature = "static_condvar",
|
||||
reason = "may be merged with Condvar in the future")]
|
||||
pub fn wait_timeout_ms<'a, T>(&'static self, guard: MutexGuard<'a, T>, ms: u32)
|
||||
-> LockResult<(MutexGuard<'a, T>, bool)> {
|
||||
self.wait_timeout(guard, Duration::from_millis(ms as u64))
|
||||
}
|
||||
|
||||
/// Waits on this condition variable for a notification, timing out after a
|
||||
/// specified duration.
|
||||
///
|
||||
/// See `Condvar::wait_timeout`.
|
||||
#[unstable(feature = "static_condvar",
|
||||
reason = "may be merged with Condvar in the future")]
|
||||
pub fn wait_timeout<'a, T>(&'static self,
|
||||
guard: MutexGuard<'a, T>,
|
||||
timeout: Duration)
|
||||
-> LockResult<(MutexGuard<'a, T>, bool)> {
|
||||
let (poisoned, success) = unsafe {
|
||||
let lock = mutex::guard_lock(&guard);
|
||||
self.verify(lock);
|
||||
let success = self.inner.wait_timeout(lock, Duration::milliseconds(ms as i64));
|
||||
let success = self.inner.wait_timeout(lock, timeout);
|
||||
(mutex::guard_poison(&guard).get(), success)
|
||||
};
|
||||
if poisoned {
|
||||
@ -259,7 +296,7 @@ impl StaticCondvar {
|
||||
/// passed and the function returns `false`.
|
||||
///
|
||||
/// See `Condvar::wait_timeout_with`.
|
||||
#[unstable(feature = "std_misc",
|
||||
#[unstable(feature = "static_condvar",
|
||||
reason = "may be merged with Condvar in the future")]
|
||||
pub fn wait_timeout_with<'a, T, F>(&'static self,
|
||||
guard: MutexGuard<'a, T>,
|
||||
@ -267,7 +304,8 @@ impl StaticCondvar {
|
||||
mut f: F)
|
||||
-> LockResult<(MutexGuard<'a, T>, bool)>
|
||||
where F: FnMut(LockResult<&mut T>) -> bool {
|
||||
// This could be made more efficient by pushing the implementation into sys::condvar
|
||||
// This could be made more efficient by pushing the implementation into
|
||||
// sys::condvar
|
||||
let start = SteadyTime::now();
|
||||
let mut guard_result: LockResult<MutexGuard<'a, T>> = Ok(guard);
|
||||
while !f(guard_result
|
||||
@ -277,12 +315,15 @@ impl StaticCondvar {
|
||||
let now = SteadyTime::now();
|
||||
let consumed = &now - &start;
|
||||
let guard = guard_result.unwrap_or_else(|e| e.into_inner());
|
||||
let res = self.wait_timeout_ms(guard, (dur - consumed).num_milliseconds() as u32);
|
||||
let (new_guard_result, no_timeout) = match res {
|
||||
Ok((new_guard, no_timeout)) => (Ok(new_guard), no_timeout),
|
||||
Err(err) => {
|
||||
let (new_guard, no_timeout) = err.into_inner();
|
||||
(Err(PoisonError::new(new_guard)), no_timeout)
|
||||
let (new_guard_result, no_timeout) = if consumed > dur {
|
||||
(Ok(guard), false)
|
||||
} else {
|
||||
match self.wait_timeout(guard, dur - consumed) {
|
||||
Ok((new_guard, no_timeout)) => (Ok(new_guard), no_timeout),
|
||||
Err(err) => {
|
||||
let (new_guard, no_timeout) = err.into_inner();
|
||||
(Err(PoisonError::new(new_guard)), no_timeout)
|
||||
}
|
||||
}
|
||||
};
|
||||
guard_result = new_guard_result;
|
||||
@ -301,14 +342,14 @@ impl StaticCondvar {
|
||||
/// Wakes up one blocked thread on this condvar.
|
||||
///
|
||||
/// See `Condvar::notify_one`.
|
||||
#[unstable(feature = "std_misc",
|
||||
#[unstable(feature = "static_condvar",
|
||||
reason = "may be merged with Condvar in the future")]
|
||||
pub fn notify_one(&'static self) { unsafe { self.inner.notify_one() } }
|
||||
|
||||
/// Wakes up all blocked threads on this condvar.
|
||||
///
|
||||
/// See `Condvar::notify_all`.
|
||||
#[unstable(feature = "std_misc",
|
||||
#[unstable(feature = "static_condvar",
|
||||
reason = "may be merged with Condvar in the future")]
|
||||
pub fn notify_all(&'static self) { unsafe { self.inner.notify_all() } }
|
||||
|
||||
@ -318,7 +359,7 @@ impl StaticCondvar {
|
||||
/// active users of the condvar, and this also doesn't prevent any future
|
||||
/// users of the condvar. This method is required to be called to not leak
|
||||
/// memory on all platforms.
|
||||
#[unstable(feature = "std_misc",
|
||||
#[unstable(feature = "static_condvar",
|
||||
reason = "may be merged with Condvar in the future")]
|
||||
pub unsafe fn destroy(&'static self) {
|
||||
self.inner.destroy()
|
||||
@ -447,7 +488,9 @@ mod tests {
|
||||
static S: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||
|
||||
let g = M.lock().unwrap();
|
||||
let (g, success) = C.wait_timeout_with(g, Duration::nanoseconds(1000), |_| false).unwrap();
|
||||
let (g, success) = C.wait_timeout_with(g, Duration::new(0, 1000), |_| {
|
||||
false
|
||||
}).unwrap();
|
||||
assert!(!success);
|
||||
|
||||
let (tx, rx) = channel();
|
||||
@ -471,7 +514,8 @@ mod tests {
|
||||
});
|
||||
|
||||
let mut state = 0;
|
||||
let (_g, success) = C.wait_timeout_with(g, Duration::days(1), |_| {
|
||||
let day = 24 * 60 * 60;
|
||||
let (_g, success) = C.wait_timeout_with(g, Duration::new(day, 0), |_| {
|
||||
assert_eq!(state, S.load(Ordering::SeqCst));
|
||||
tx.send(()).unwrap();
|
||||
state += 1;
|
||||
|
@ -57,25 +57,20 @@ impl Condvar {
|
||||
// https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46
|
||||
// https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367
|
||||
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
|
||||
if dur <= Duration::zero() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// First, figure out what time it currently is, in both system and stable time.
|
||||
// pthread_cond_timedwait uses system time, but we want to report timeout based on stable
|
||||
// time.
|
||||
// First, figure out what time it currently is, in both system and
|
||||
// stable time. pthread_cond_timedwait uses system time, but we want to
|
||||
// report timeout based on stable time.
|
||||
let mut sys_now = libc::timeval { tv_sec: 0, tv_usec: 0 };
|
||||
let stable_now = time::SteadyTime::now();
|
||||
let r = ffi::gettimeofday(&mut sys_now, ptr::null_mut());
|
||||
debug_assert_eq!(r, 0);
|
||||
|
||||
let seconds = dur.num_seconds() as libc::time_t;
|
||||
let seconds = dur.secs() as libc::time_t;
|
||||
let timeout = match sys_now.tv_sec.checked_add(seconds) {
|
||||
Some(sec) => {
|
||||
libc::timespec {
|
||||
tv_sec: sec,
|
||||
tv_nsec: (dur - Duration::seconds(dur.num_seconds()))
|
||||
.num_nanoseconds().unwrap() as libc::c_long,
|
||||
tv_nsec: dur.extra_nanos() as libc::c_long,
|
||||
}
|
||||
}
|
||||
None => {
|
||||
@ -87,11 +82,12 @@ impl Condvar {
|
||||
};
|
||||
|
||||
// And wait!
|
||||
let r = ffi::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex), &timeout);
|
||||
let r = ffi::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex),
|
||||
&timeout);
|
||||
debug_assert!(r == libc::ETIMEDOUT || r == 0);
|
||||
|
||||
// ETIMEDOUT is not a totally reliable method of determining timeout due to clock shifts,
|
||||
// so do the check ourselves
|
||||
// ETIMEDOUT is not a totally reliable method of determining timeout due
|
||||
// to clock shifts, so do the check ourselves
|
||||
&time::SteadyTime::now() - &stable_now < dur
|
||||
}
|
||||
|
||||
|
@ -129,14 +129,9 @@ impl Thread {
|
||||
}
|
||||
|
||||
pub fn sleep(dur: Duration) {
|
||||
if dur < Duration::zero() {
|
||||
return Thread::yield_now()
|
||||
}
|
||||
let seconds = dur.num_seconds();
|
||||
let ns = dur - Duration::seconds(seconds);
|
||||
let mut ts = libc::timespec {
|
||||
tv_sec: seconds as libc::time_t,
|
||||
tv_nsec: ns.num_nanoseconds().unwrap() as libc::c_long,
|
||||
tv_sec: dur.secs() as libc::time_t,
|
||||
tv_nsec: dur.extra_nanos() as libc::c_long,
|
||||
};
|
||||
|
||||
// If we're awoken with a signal then the return value will be -1 and
|
||||
|
@ -10,12 +10,15 @@
|
||||
|
||||
pub use self::inner::SteadyTime;
|
||||
|
||||
const NSEC_PER_SEC: u64 = 1_000_000_000;
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||
mod inner {
|
||||
use libc;
|
||||
use time::Duration;
|
||||
use ops::Sub;
|
||||
use sync::{Once, ONCE_INIT};
|
||||
use super::NSEC_PER_SEC;
|
||||
|
||||
pub struct SteadyTime {
|
||||
t: u64
|
||||
@ -32,11 +35,6 @@ mod inner {
|
||||
t: unsafe { mach_absolute_time() },
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ns(&self) -> u64 {
|
||||
let info = info();
|
||||
self.t * info.numer as u64 / info.denom as u64
|
||||
}
|
||||
}
|
||||
|
||||
fn info() -> &'static libc::mach_timebase_info {
|
||||
@ -59,8 +57,9 @@ mod inner {
|
||||
|
||||
fn sub(self, other: &SteadyTime) -> Duration {
|
||||
let info = info();
|
||||
let diff = self.t as i64 - other.t as i64;
|
||||
Duration::nanoseconds(diff * info.numer as i64 / info.denom as i64)
|
||||
let diff = self.t as u64 - other.t as u64;
|
||||
let nanos = diff * info.numer as u64 / info.denom as u64;
|
||||
Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -70,8 +69,7 @@ mod inner {
|
||||
use libc;
|
||||
use time::Duration;
|
||||
use ops::Sub;
|
||||
|
||||
const NSEC_PER_SEC: i64 = 1_000_000_000;
|
||||
use super::NSEC_PER_SEC;
|
||||
|
||||
pub struct SteadyTime {
|
||||
t: libc::timespec,
|
||||
@ -104,10 +102,6 @@ mod inner {
|
||||
}
|
||||
t
|
||||
}
|
||||
|
||||
pub fn ns(&self) -> u64 {
|
||||
self.t.tv_sec as u64 * NSEC_PER_SEC as u64 + self.t.tv_nsec as u64
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Sub for &'a SteadyTime {
|
||||
@ -115,12 +109,12 @@ mod inner {
|
||||
|
||||
fn sub(self, other: &SteadyTime) -> Duration {
|
||||
if self.t.tv_nsec >= other.t.tv_nsec {
|
||||
Duration::seconds(self.t.tv_sec as i64 - other.t.tv_sec as i64) +
|
||||
Duration::nanoseconds(self.t.tv_nsec as i64 - other.t.tv_nsec as i64)
|
||||
Duration::new(self.t.tv_sec as u64 - other.t.tv_sec as u64,
|
||||
self.t.tv_nsec as u32 - other.t.tv_nsec as u32)
|
||||
} else {
|
||||
Duration::seconds(self.t.tv_sec as i64 - 1 - other.t.tv_sec as i64) +
|
||||
Duration::nanoseconds(self.t.tv_nsec as i64 + NSEC_PER_SEC -
|
||||
other.t.tv_nsec as i64)
|
||||
Duration::new(self.t.tv_sec as u64 - 1 - other.t.tv_sec as u64,
|
||||
self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) -
|
||||
other.t.tv_nsec as u32)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -482,7 +482,23 @@ pub fn catch_panic<F, R>(f: F) -> Result<R>
|
||||
/// spurious wakeup.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn sleep_ms(ms: u32) {
|
||||
imp::Thread::sleep(Duration::milliseconds(ms as i64))
|
||||
sleep(Duration::from_millis(ms as u64))
|
||||
}
|
||||
|
||||
/// Puts the current thread to sleep for the specified amount of time.
|
||||
///
|
||||
/// The thread may sleep longer than the duration specified due to scheduling
|
||||
/// specifics or platform-dependent functionality.
|
||||
///
|
||||
/// # Platform behavior
|
||||
///
|
||||
/// On Unix platforms this function will not return early due to a
|
||||
/// signal being received or a spurious wakeup. Platforms which do not support
|
||||
/// nanosecond precision for sleeping will have `dur` rounded up to the nearest
|
||||
/// granularity of time they can sleep for.
|
||||
#[unstable(feature = "thread_sleep", reason = "waiting on Duration")]
|
||||
pub fn sleep(dur: Duration) {
|
||||
imp::Thread::sleep(dur)
|
||||
}
|
||||
|
||||
/// Blocks unless or until the current thread's token is made available (may wake spuriously).
|
||||
@ -508,18 +524,38 @@ pub fn park() {
|
||||
/// the specified duration has been reached (may wake spuriously).
|
||||
///
|
||||
/// The semantics of this function are equivalent to `park()` except that the
|
||||
/// thread will be blocked for roughly no longer than *duration*. This method
|
||||
/// thread will be blocked for roughly no longer than *ms*. This method
|
||||
/// should not be used for precise timing due to anomalies such as
|
||||
/// preemption or platform differences that may not cause the maximum
|
||||
/// amount of time waited to be precisely *duration* long.
|
||||
/// amount of time waited to be precisely *ms* long.
|
||||
///
|
||||
/// See the module doc for more detail.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn park_timeout_ms(ms: u32) {
|
||||
park_timeout(Duration::from_millis(ms as u64))
|
||||
}
|
||||
|
||||
/// Blocks unless or until the current thread's token is made available or
|
||||
/// the specified duration has been reached (may wake spuriously).
|
||||
///
|
||||
/// The semantics of this function are equivalent to `park()` except that the
|
||||
/// thread will be blocked for roughly no longer than *dur*. This method
|
||||
/// should not be used for precise timing due to anomalies such as
|
||||
/// preemption or platform differences that may not cause the maximum
|
||||
/// amount of time waited to be precisely *dur* long.
|
||||
///
|
||||
/// See the module doc for more detail.
|
||||
///
|
||||
/// # Platform behavior
|
||||
///
|
||||
/// Platforms which do not support nanosecond precision for sleeping will have
|
||||
/// `dur` rounded up to the nearest granularity of time they can sleep for.
|
||||
#[unstable(feature = "park_timeout", reason = "waiting on Duration")]
|
||||
pub fn park_timeout(dur: Duration) {
|
||||
let thread = current();
|
||||
let mut guard = thread.inner.lock.lock().unwrap();
|
||||
if !*guard {
|
||||
let (g, _) = thread.inner.cvar.wait_timeout_ms(guard, ms).unwrap();
|
||||
let (g, _) = thread.inner.cvar.wait_timeout(guard, dur).unwrap();
|
||||
guard = g;
|
||||
}
|
||||
*guard = false;
|
||||
|
@ -10,589 +10,265 @@
|
||||
|
||||
//! Temporal quantification
|
||||
|
||||
#![unstable(feature = "std_misc")]
|
||||
#![unstable(feature = "duration", reason = "recently added API per RFC 1040")]
|
||||
|
||||
use prelude::v1::*;
|
||||
|
||||
use {fmt, i64};
|
||||
use ops::{Add, Sub, Mul, Div, Neg};
|
||||
use fmt;
|
||||
use ops::{Add, Sub, Mul, Div};
|
||||
use sys::time::SteadyTime;
|
||||
|
||||
/// The number of nanoseconds in a microsecond.
|
||||
const NANOS_PER_MICRO: i32 = 1000;
|
||||
/// The number of nanoseconds in a millisecond.
|
||||
const NANOS_PER_MILLI: i32 = 1000_000;
|
||||
/// The number of nanoseconds in seconds.
|
||||
const NANOS_PER_SEC: i32 = 1_000_000_000;
|
||||
/// The number of microseconds per second.
|
||||
const MICROS_PER_SEC: i64 = 1000_000;
|
||||
/// The number of milliseconds per second.
|
||||
const MILLIS_PER_SEC: i64 = 1000;
|
||||
/// The number of seconds in a minute.
|
||||
const SECS_PER_MINUTE: i64 = 60;
|
||||
/// The number of seconds in an hour.
|
||||
const SECS_PER_HOUR: i64 = 3600;
|
||||
/// The number of (non-leap) seconds in days.
|
||||
const SECS_PER_DAY: i64 = 86400;
|
||||
/// The number of (non-leap) seconds in a week.
|
||||
const SECS_PER_WEEK: i64 = 604800;
|
||||
const NANOS_PER_SEC: u32 = 1_000_000_000;
|
||||
const NANOS_PER_MILLI: u32 = 1_000_000;
|
||||
const MILLIS_PER_SEC: u64 = 1_000;
|
||||
|
||||
macro_rules! try_opt {
|
||||
($e:expr) => (match $e { Some(v) => v, None => return None })
|
||||
}
|
||||
|
||||
|
||||
/// ISO 8601 time duration with nanosecond precision.
|
||||
/// This also allows for the negative duration; see individual methods for details.
|
||||
#[unstable(feature = "std_misc")]
|
||||
/// A duration type to represent a span of time, typically used for system
|
||||
/// timeouts.
|
||||
///
|
||||
/// Each duration is composed of a number of seconds and nanosecond precision.
|
||||
/// APIs binding a system timeout will typically round up the nanosecond
|
||||
/// precision if the underlying system does not support that level of precision.
|
||||
///
|
||||
/// Durations implement many common traits, including `Add`, `Sub`, and other
|
||||
/// ops traits. Currently a duration may only be inspected for its number of
|
||||
/// seconds and its nanosecond precision.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(duration)]
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let five_seconds = Duration::new(5, 0);
|
||||
/// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5);
|
||||
///
|
||||
/// assert_eq!(five_seconds_and_five_nanos.secs(), 5);
|
||||
/// assert_eq!(five_seconds_and_five_nanos.extra_nanos(), 5);
|
||||
///
|
||||
/// let ten_millis = Duration::from_millis(10);
|
||||
/// ```
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
pub struct Duration {
|
||||
secs: i64,
|
||||
nanos: i32, // Always 0 <= nanos < NANOS_PER_SEC
|
||||
secs: u64,
|
||||
nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC
|
||||
}
|
||||
|
||||
/// The minimum possible `Duration`: `i64::MIN` milliseconds.
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub const MIN: Duration = Duration {
|
||||
secs: i64::MIN / MILLIS_PER_SEC - 1,
|
||||
nanos: NANOS_PER_SEC + (i64::MIN % MILLIS_PER_SEC) as i32 * NANOS_PER_MILLI
|
||||
};
|
||||
|
||||
/// The maximum possible `Duration`: `i64::MAX` milliseconds.
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub const MAX: Duration = Duration {
|
||||
secs: i64::MAX / MILLIS_PER_SEC,
|
||||
nanos: (i64::MAX % MILLIS_PER_SEC) as i32 * NANOS_PER_MILLI
|
||||
};
|
||||
|
||||
impl Duration {
|
||||
/// Makes a new `Duration` with given number of weeks.
|
||||
/// Equivalent to `Duration::seconds(weeks * 7 * 24 * 60 * 60)` with overflow checks.
|
||||
/// Panics when the duration is out of bounds.
|
||||
#[inline]
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn weeks(weeks: i64) -> Duration {
|
||||
let secs = weeks.checked_mul(SECS_PER_WEEK).expect("Duration::weeks out of bounds");
|
||||
Duration::seconds(secs)
|
||||
}
|
||||
|
||||
/// Makes a new `Duration` with given number of days.
|
||||
/// Equivalent to `Duration::seconds(days * 24 * 60 * 60)` with overflow checks.
|
||||
/// Panics when the duration is out of bounds.
|
||||
#[inline]
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn days(days: i64) -> Duration {
|
||||
let secs = days.checked_mul(SECS_PER_DAY).expect("Duration::days out of bounds");
|
||||
Duration::seconds(secs)
|
||||
}
|
||||
|
||||
/// Makes a new `Duration` with given number of hours.
|
||||
/// Equivalent to `Duration::seconds(hours * 60 * 60)` with overflow checks.
|
||||
/// Panics when the duration is out of bounds.
|
||||
#[inline]
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn hours(hours: i64) -> Duration {
|
||||
let secs = hours.checked_mul(SECS_PER_HOUR).expect("Duration::hours ouf of bounds");
|
||||
Duration::seconds(secs)
|
||||
}
|
||||
|
||||
/// Makes a new `Duration` with given number of minutes.
|
||||
/// Equivalent to `Duration::seconds(minutes * 60)` with overflow checks.
|
||||
/// Panics when the duration is out of bounds.
|
||||
#[inline]
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn minutes(minutes: i64) -> Duration {
|
||||
let secs = minutes.checked_mul(SECS_PER_MINUTE).expect("Duration::minutes out of bounds");
|
||||
Duration::seconds(secs)
|
||||
}
|
||||
|
||||
/// Makes a new `Duration` with given number of seconds.
|
||||
/// Panics when the duration is more than `i64::MAX` milliseconds
|
||||
/// or less than `i64::MIN` milliseconds.
|
||||
#[inline]
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn seconds(seconds: i64) -> Duration {
|
||||
let d = Duration { secs: seconds, nanos: 0 };
|
||||
if d < MIN || d > MAX {
|
||||
panic!("Duration::seconds out of bounds");
|
||||
}
|
||||
d
|
||||
}
|
||||
|
||||
/// Makes a new `Duration` with given number of milliseconds.
|
||||
#[inline]
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn milliseconds(milliseconds: i64) -> Duration {
|
||||
let (secs, millis) = div_mod_floor_64(milliseconds, MILLIS_PER_SEC);
|
||||
let nanos = millis as i32 * NANOS_PER_MILLI;
|
||||
/// Crates a new `Duration` from the specified number of seconds and
|
||||
/// additional nanosecond precision.
|
||||
///
|
||||
/// If the nanoseconds is greater than 1 billion (the number of nanoseconds
|
||||
/// in a second), then it will carry over into the seconds provided.
|
||||
pub fn new(secs: u64, nanos: u32) -> Duration {
|
||||
let secs = secs + (nanos / NANOS_PER_SEC) as u64;
|
||||
let nanos = nanos % NANOS_PER_SEC;
|
||||
Duration { secs: secs, nanos: nanos }
|
||||
}
|
||||
|
||||
/// Makes a new `Duration` with given number of microseconds.
|
||||
#[inline]
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn microseconds(microseconds: i64) -> Duration {
|
||||
let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
|
||||
let nanos = micros as i32 * NANOS_PER_MICRO;
|
||||
Duration { secs: secs, nanos: nanos }
|
||||
}
|
||||
|
||||
/// Makes a new `Duration` with given number of nanoseconds.
|
||||
#[inline]
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn nanoseconds(nanos: i64) -> Duration {
|
||||
let (secs, nanos) = div_mod_floor_64(nanos, NANOS_PER_SEC as i64);
|
||||
Duration { secs: secs, nanos: nanos as i32 }
|
||||
}
|
||||
|
||||
/// Runs a closure, returning the duration of time it took to run the
|
||||
/// closure.
|
||||
#[unstable(feature = "std_misc")]
|
||||
#[unstable(feature = "duration_span",
|
||||
reason = "unsure if this is the right API or whether it should \
|
||||
wait for a more general \"moment in time\" \
|
||||
abstraction")]
|
||||
pub fn span<F>(f: F) -> Duration where F: FnOnce() {
|
||||
let before = super::precise_time_ns();
|
||||
let start = SteadyTime::now();
|
||||
f();
|
||||
Duration::nanoseconds((super::precise_time_ns() - before) as i64)
|
||||
&SteadyTime::now() - &start
|
||||
}
|
||||
|
||||
/// Returns the total number of whole weeks in the duration.
|
||||
#[inline]
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn num_weeks(&self) -> i64 {
|
||||
self.num_days() / 7
|
||||
/// Creates a new `Duration` from the specified number of seconds.
|
||||
pub fn from_secs(secs: u64) -> Duration {
|
||||
Duration { secs: secs, nanos: 0 }
|
||||
}
|
||||
|
||||
/// Returns the total number of whole days in the duration.
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn num_days(&self) -> i64 {
|
||||
self.num_seconds() / SECS_PER_DAY
|
||||
/// Creates a new `Duration` from the specified number of milliseconds.
|
||||
pub fn from_millis(millis: u64) -> Duration {
|
||||
let secs = millis / MILLIS_PER_SEC;
|
||||
let nanos = ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI;
|
||||
Duration { secs: secs, nanos: nanos }
|
||||
}
|
||||
|
||||
/// Returns the total number of whole hours in the duration.
|
||||
#[inline]
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn num_hours(&self) -> i64 {
|
||||
self.num_seconds() / SECS_PER_HOUR
|
||||
}
|
||||
/// Returns the number of whole seconds represented by this duration.
|
||||
///
|
||||
/// The extra precision represented by this duration is ignored (e.g. extra
|
||||
/// nanoseconds are not represented in the returned value).
|
||||
pub fn secs(&self) -> u64 { self.secs }
|
||||
|
||||
/// Returns the total number of whole minutes in the duration.
|
||||
#[inline]
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn num_minutes(&self) -> i64 {
|
||||
self.num_seconds() / SECS_PER_MINUTE
|
||||
}
|
||||
|
||||
/// Returns the total number of whole seconds in the duration.
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn num_seconds(&self) -> i64 {
|
||||
// If secs is negative, nanos should be subtracted from the duration.
|
||||
if self.secs < 0 && self.nanos > 0 {
|
||||
self.secs + 1
|
||||
} else {
|
||||
self.secs
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of nanoseconds such that
|
||||
/// `nanos_mod_sec() + num_seconds() * NANOS_PER_SEC` is the total number of
|
||||
/// nanoseconds in the duration.
|
||||
fn nanos_mod_sec(&self) -> i32 {
|
||||
if self.secs < 0 && self.nanos > 0 {
|
||||
self.nanos - NANOS_PER_SEC
|
||||
} else {
|
||||
self.nanos
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the total number of whole milliseconds in the duration,
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn num_milliseconds(&self) -> i64 {
|
||||
// A proper Duration will not overflow, because MIN and MAX are defined
|
||||
// such that the range is exactly i64 milliseconds.
|
||||
let secs_part = self.num_seconds() * MILLIS_PER_SEC;
|
||||
let nanos_part = self.nanos_mod_sec() / NANOS_PER_MILLI;
|
||||
secs_part + nanos_part as i64
|
||||
}
|
||||
|
||||
/// Returns the total number of whole microseconds in the duration,
|
||||
/// or `None` on overflow (exceeding 2^63 microseconds in either direction).
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn num_microseconds(&self) -> Option<i64> {
|
||||
let secs_part = try_opt!(self.num_seconds().checked_mul(MICROS_PER_SEC));
|
||||
let nanos_part = self.nanos_mod_sec() / NANOS_PER_MICRO;
|
||||
secs_part.checked_add(nanos_part as i64)
|
||||
}
|
||||
|
||||
/// Returns the total number of whole nanoseconds in the duration,
|
||||
/// or `None` on overflow (exceeding 2^63 nanoseconds in either direction).
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn num_nanoseconds(&self) -> Option<i64> {
|
||||
let secs_part = try_opt!(self.num_seconds().checked_mul(NANOS_PER_SEC as i64));
|
||||
let nanos_part = self.nanos_mod_sec();
|
||||
secs_part.checked_add(nanos_part as i64)
|
||||
}
|
||||
|
||||
/// Add two durations, returning `None` if overflow occurred.
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn checked_add(&self, rhs: &Duration) -> Option<Duration> {
|
||||
let mut secs = try_opt!(self.secs.checked_add(rhs.secs));
|
||||
let mut nanos = self.nanos + rhs.nanos;
|
||||
if nanos >= NANOS_PER_SEC {
|
||||
nanos -= NANOS_PER_SEC;
|
||||
secs = try_opt!(secs.checked_add(1));
|
||||
}
|
||||
let d = Duration { secs: secs, nanos: nanos };
|
||||
// Even if d is within the bounds of i64 seconds,
|
||||
// it might still overflow i64 milliseconds.
|
||||
if d < MIN || d > MAX { None } else { Some(d) }
|
||||
}
|
||||
|
||||
/// Subtract two durations, returning `None` if overflow occurred.
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn checked_sub(&self, rhs: &Duration) -> Option<Duration> {
|
||||
let mut secs = try_opt!(self.secs.checked_sub(rhs.secs));
|
||||
let mut nanos = self.nanos - rhs.nanos;
|
||||
if nanos < 0 {
|
||||
nanos += NANOS_PER_SEC;
|
||||
secs = try_opt!(secs.checked_sub(1));
|
||||
}
|
||||
let d = Duration { secs: secs, nanos: nanos };
|
||||
// Even if d is within the bounds of i64 seconds,
|
||||
// it might still overflow i64 milliseconds.
|
||||
if d < MIN || d > MAX { None } else { Some(d) }
|
||||
}
|
||||
|
||||
/// The minimum possible `Duration`: `i64::MIN` milliseconds.
|
||||
#[inline]
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn min_value() -> Duration { MIN }
|
||||
|
||||
/// The maximum possible `Duration`: `i64::MAX` milliseconds.
|
||||
#[inline]
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn max_value() -> Duration { MAX }
|
||||
|
||||
/// A duration where the stored seconds and nanoseconds are equal to zero.
|
||||
#[inline]
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn zero() -> Duration {
|
||||
Duration { secs: 0, nanos: 0 }
|
||||
}
|
||||
|
||||
/// Returns `true` if the duration equals `Duration::zero()`.
|
||||
#[inline]
|
||||
#[unstable(feature = "std_misc")]
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.secs == 0 && self.nanos == 0
|
||||
}
|
||||
/// Returns the nanosecond precision represented by this duration.
|
||||
///
|
||||
/// This method does **not** return the length of the duration when
|
||||
/// represented by nanoseconds. The returned number always represents a
|
||||
/// fractional portion of a second (e.g. it is less than one billion).
|
||||
pub fn extra_nanos(&self) -> u32 { self.nanos }
|
||||
}
|
||||
|
||||
#[unstable(feature = "std_misc")]
|
||||
impl Neg for Duration {
|
||||
type Output = Duration;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> Duration {
|
||||
if self.nanos == 0 {
|
||||
Duration { secs: -self.secs, nanos: 0 }
|
||||
} else {
|
||||
Duration { secs: -self.secs - 1, nanos: NANOS_PER_SEC - self.nanos }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "std_misc")]
|
||||
impl Add for Duration {
|
||||
type Output = Duration;
|
||||
|
||||
fn add(self, rhs: Duration) -> Duration {
|
||||
let mut secs = self.secs + rhs.secs;
|
||||
let mut secs = self.secs.checked_add(rhs.secs)
|
||||
.expect("overflow when adding durations");
|
||||
let mut nanos = self.nanos + rhs.nanos;
|
||||
if nanos >= NANOS_PER_SEC {
|
||||
nanos -= NANOS_PER_SEC;
|
||||
secs += 1;
|
||||
secs = secs.checked_add(1).expect("overflow when adding durations");
|
||||
}
|
||||
debug_assert!(nanos < NANOS_PER_SEC);
|
||||
Duration { secs: secs, nanos: nanos }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "std_misc")]
|
||||
impl Sub for Duration {
|
||||
type Output = Duration;
|
||||
|
||||
fn sub(self, rhs: Duration) -> Duration {
|
||||
let mut secs = self.secs - rhs.secs;
|
||||
let mut nanos = self.nanos - rhs.nanos;
|
||||
if nanos < 0 {
|
||||
nanos += NANOS_PER_SEC;
|
||||
secs -= 1;
|
||||
}
|
||||
let mut secs = self.secs.checked_sub(rhs.secs)
|
||||
.expect("overflow when subtracting durations");
|
||||
let nanos = if self.nanos >= rhs.nanos {
|
||||
self.nanos - rhs.nanos
|
||||
} else {
|
||||
secs = secs.checked_sub(1)
|
||||
.expect("overflow when subtracting durations");
|
||||
self.nanos + NANOS_PER_SEC - rhs.nanos
|
||||
};
|
||||
debug_assert!(nanos < NANOS_PER_SEC);
|
||||
Duration { secs: secs, nanos: nanos }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "std_misc")]
|
||||
impl Mul<i32> for Duration {
|
||||
impl Mul<u32> for Duration {
|
||||
type Output = Duration;
|
||||
|
||||
fn mul(self, rhs: i32) -> Duration {
|
||||
// Multiply nanoseconds as i64, because it cannot overflow that way.
|
||||
let total_nanos = self.nanos as i64 * rhs as i64;
|
||||
let (extra_secs, nanos) = div_mod_floor_64(total_nanos, NANOS_PER_SEC as i64);
|
||||
let secs = self.secs * rhs as i64 + extra_secs;
|
||||
Duration { secs: secs, nanos: nanos as i32 }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "std_misc")]
|
||||
impl Div<i32> for Duration {
|
||||
type Output = Duration;
|
||||
|
||||
fn div(self, rhs: i32) -> Duration {
|
||||
let mut secs = self.secs / rhs as i64;
|
||||
let carry = self.secs - secs * rhs as i64;
|
||||
let extra_nanos = carry * NANOS_PER_SEC as i64 / rhs as i64;
|
||||
let mut nanos = self.nanos / rhs + extra_nanos as i32;
|
||||
if nanos >= NANOS_PER_SEC {
|
||||
nanos -= NANOS_PER_SEC;
|
||||
secs += 1;
|
||||
}
|
||||
if nanos < 0 {
|
||||
nanos += NANOS_PER_SEC;
|
||||
secs -= 1;
|
||||
}
|
||||
fn mul(self, rhs: u32) -> Duration {
|
||||
// Multiply nanoseconds as u64, because it cannot overflow that way.
|
||||
let total_nanos = self.nanos as u64 * rhs as u64;
|
||||
let extra_secs = total_nanos / (NANOS_PER_SEC as u64);
|
||||
let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32;
|
||||
let secs = self.secs.checked_mul(rhs as u64)
|
||||
.and_then(|s| s.checked_add(extra_secs))
|
||||
.expect("overflow when multiplying duration");
|
||||
debug_assert!(nanos < NANOS_PER_SEC);
|
||||
Duration { secs: secs, nanos: nanos }
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<u32> for Duration {
|
||||
type Output = Duration;
|
||||
|
||||
fn div(self, rhs: u32) -> Duration {
|
||||
let secs = self.secs / (rhs as u64);
|
||||
let carry = self.secs - secs * (rhs as u64);
|
||||
let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64);
|
||||
let nanos = self.nanos / rhs + (extra_nanos as u32);
|
||||
debug_assert!(nanos < NANOS_PER_SEC);
|
||||
Duration { secs: secs, nanos: nanos }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Display for Duration {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
// technically speaking, negative duration is not valid ISO 8601,
|
||||
// but we need to print it anyway.
|
||||
let (abs, sign) = if self.secs < 0 { (-*self, "-") } else { (*self, "") };
|
||||
|
||||
let days = abs.secs / SECS_PER_DAY;
|
||||
let secs = abs.secs - days * SECS_PER_DAY;
|
||||
let hasdate = days != 0;
|
||||
let hastime = (secs != 0 || abs.nanos != 0) || !hasdate;
|
||||
|
||||
try!(write!(f, "{}P", sign));
|
||||
|
||||
if hasdate {
|
||||
try!(write!(f, "{}D", days));
|
||||
match (self.secs, self.nanos) {
|
||||
(s, 0) => write!(f, "{}s", s),
|
||||
(0, n) if n % NANOS_PER_MILLI == 0 => write!(f, "{}ms",
|
||||
n / NANOS_PER_MILLI),
|
||||
(0, n) if n % 1_000 == 0 => write!(f, "{}µs", n / 1_000),
|
||||
(0, n) => write!(f, "{}ns", n),
|
||||
(s, n) => write!(f, "{}.{}s", s,
|
||||
format!("{:09}", n).trim_right_matches('0'))
|
||||
}
|
||||
if hastime {
|
||||
if abs.nanos == 0 {
|
||||
try!(write!(f, "T{}S", secs));
|
||||
} else if abs.nanos % NANOS_PER_MILLI == 0 {
|
||||
try!(write!(f, "T{}.{:03}S", secs, abs.nanos / NANOS_PER_MILLI));
|
||||
} else if abs.nanos % NANOS_PER_MICRO == 0 {
|
||||
try!(write!(f, "T{}.{:06}S", secs, abs.nanos / NANOS_PER_MICRO));
|
||||
} else {
|
||||
try!(write!(f, "T{}.{:09}S", secs, abs.nanos));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Copied from libnum
|
||||
#[inline]
|
||||
fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) {
|
||||
(div_floor_64(this, other), mod_floor_64(this, other))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn div_floor_64(this: i64, other: i64) -> i64 {
|
||||
match div_rem_64(this, other) {
|
||||
(d, r) if (r > 0 && other < 0)
|
||||
|| (r < 0 && other > 0) => d - 1,
|
||||
(d, _) => d,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mod_floor_64(this: i64, other: i64) -> i64 {
|
||||
match this % other {
|
||||
r if (r > 0 && other < 0)
|
||||
|| (r < 0 && other > 0) => r + other,
|
||||
r => r,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
|
||||
(this / other, this % other)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Duration, MIN, MAX};
|
||||
use {i32, i64};
|
||||
use option::Option::{Some, None};
|
||||
use string::ToString;
|
||||
use prelude::v1::*;
|
||||
use super::Duration;
|
||||
|
||||
#[test]
|
||||
fn test_duration() {
|
||||
assert!(Duration::seconds(1) != Duration::zero());
|
||||
assert_eq!(Duration::seconds(1) + Duration::seconds(2), Duration::seconds(3));
|
||||
assert_eq!(Duration::seconds(86399) + Duration::seconds(4),
|
||||
Duration::days(1) + Duration::seconds(3));
|
||||
assert_eq!(Duration::days(10) - Duration::seconds(1000), Duration::seconds(863000));
|
||||
assert_eq!(Duration::days(10) - Duration::seconds(1000000), Duration::seconds(-136000));
|
||||
assert_eq!(Duration::days(2) + Duration::seconds(86399) +
|
||||
Duration::nanoseconds(1234567890),
|
||||
Duration::days(3) + Duration::nanoseconds(234567890));
|
||||
assert_eq!(-Duration::days(3), Duration::days(-3));
|
||||
assert_eq!(-(Duration::days(3) + Duration::seconds(70)),
|
||||
Duration::days(-4) + Duration::seconds(86400-70));
|
||||
fn creation() {
|
||||
assert!(Duration::from_secs(1) != Duration::from_secs(0));
|
||||
assert_eq!(Duration::from_secs(1) + Duration::from_secs(2),
|
||||
Duration::from_secs(3));
|
||||
assert_eq!(Duration::from_millis(10) + Duration::from_secs(4),
|
||||
Duration::new(4, 10 * 1_000_000));
|
||||
assert_eq!(Duration::from_millis(4000), Duration::new(4, 0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_duration_num_days() {
|
||||
assert_eq!(Duration::zero().num_days(), 0);
|
||||
assert_eq!(Duration::days(1).num_days(), 1);
|
||||
assert_eq!(Duration::days(-1).num_days(), -1);
|
||||
assert_eq!(Duration::seconds(86399).num_days(), 0);
|
||||
assert_eq!(Duration::seconds(86401).num_days(), 1);
|
||||
assert_eq!(Duration::seconds(-86399).num_days(), 0);
|
||||
assert_eq!(Duration::seconds(-86401).num_days(), -1);
|
||||
assert_eq!(Duration::days(i32::MAX as i64).num_days(), i32::MAX as i64);
|
||||
assert_eq!(Duration::days(i32::MIN as i64).num_days(), i32::MIN as i64);
|
||||
fn secs() {
|
||||
assert_eq!(Duration::new(0, 0).secs(), 0);
|
||||
assert_eq!(Duration::from_secs(1).secs(), 1);
|
||||
assert_eq!(Duration::from_millis(999).secs(), 0);
|
||||
assert_eq!(Duration::from_millis(1001).secs(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_duration_num_seconds() {
|
||||
assert_eq!(Duration::zero().num_seconds(), 0);
|
||||
assert_eq!(Duration::seconds(1).num_seconds(), 1);
|
||||
assert_eq!(Duration::seconds(-1).num_seconds(), -1);
|
||||
assert_eq!(Duration::milliseconds(999).num_seconds(), 0);
|
||||
assert_eq!(Duration::milliseconds(1001).num_seconds(), 1);
|
||||
assert_eq!(Duration::milliseconds(-999).num_seconds(), 0);
|
||||
assert_eq!(Duration::milliseconds(-1001).num_seconds(), -1);
|
||||
fn nanos() {
|
||||
assert_eq!(Duration::new(0, 0).extra_nanos(), 0);
|
||||
assert_eq!(Duration::new(0, 5).extra_nanos(), 5);
|
||||
assert_eq!(Duration::new(0, 1_000_000_001).extra_nanos(), 1);
|
||||
assert_eq!(Duration::from_secs(1).extra_nanos(), 0);
|
||||
assert_eq!(Duration::from_millis(999).extra_nanos(), 999 * 1_000_000);
|
||||
assert_eq!(Duration::from_millis(1001).extra_nanos(), 1 * 1_000_000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_duration_num_milliseconds() {
|
||||
assert_eq!(Duration::zero().num_milliseconds(), 0);
|
||||
assert_eq!(Duration::milliseconds(1).num_milliseconds(), 1);
|
||||
assert_eq!(Duration::milliseconds(-1).num_milliseconds(), -1);
|
||||
assert_eq!(Duration::microseconds(999).num_milliseconds(), 0);
|
||||
assert_eq!(Duration::microseconds(1001).num_milliseconds(), 1);
|
||||
assert_eq!(Duration::microseconds(-999).num_milliseconds(), 0);
|
||||
assert_eq!(Duration::microseconds(-1001).num_milliseconds(), -1);
|
||||
assert_eq!(Duration::milliseconds(i64::MAX).num_milliseconds(), i64::MAX);
|
||||
assert_eq!(Duration::milliseconds(i64::MIN).num_milliseconds(), i64::MIN);
|
||||
assert_eq!(MAX.num_milliseconds(), i64::MAX);
|
||||
assert_eq!(MIN.num_milliseconds(), i64::MIN);
|
||||
fn add() {
|
||||
assert_eq!(Duration::new(0, 0) + Duration::new(0, 1),
|
||||
Duration::new(0, 1));
|
||||
assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001),
|
||||
Duration::new(1, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_duration_num_microseconds() {
|
||||
assert_eq!(Duration::zero().num_microseconds(), Some(0));
|
||||
assert_eq!(Duration::microseconds(1).num_microseconds(), Some(1));
|
||||
assert_eq!(Duration::microseconds(-1).num_microseconds(), Some(-1));
|
||||
assert_eq!(Duration::nanoseconds(999).num_microseconds(), Some(0));
|
||||
assert_eq!(Duration::nanoseconds(1001).num_microseconds(), Some(1));
|
||||
assert_eq!(Duration::nanoseconds(-999).num_microseconds(), Some(0));
|
||||
assert_eq!(Duration::nanoseconds(-1001).num_microseconds(), Some(-1));
|
||||
assert_eq!(Duration::microseconds(i64::MAX).num_microseconds(), Some(i64::MAX));
|
||||
assert_eq!(Duration::microseconds(i64::MIN).num_microseconds(), Some(i64::MIN));
|
||||
assert_eq!(MAX.num_microseconds(), None);
|
||||
assert_eq!(MIN.num_microseconds(), None);
|
||||
fn sub() {
|
||||
assert_eq!(Duration::new(0, 1) - Duration::new(0, 0),
|
||||
Duration::new(0, 1));
|
||||
assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000),
|
||||
Duration::new(0, 1));
|
||||
assert_eq!(Duration::new(1, 0) - Duration::new(0, 1),
|
||||
Duration::new(0, 999_999_999));
|
||||
}
|
||||
|
||||
// overflow checks
|
||||
const MICROS_PER_DAY: i64 = 86400_000_000;
|
||||
assert_eq!(Duration::days(i64::MAX / MICROS_PER_DAY).num_microseconds(),
|
||||
Some(i64::MAX / MICROS_PER_DAY * MICROS_PER_DAY));
|
||||
assert_eq!(Duration::days(i64::MIN / MICROS_PER_DAY).num_microseconds(),
|
||||
Some(i64::MIN / MICROS_PER_DAY * MICROS_PER_DAY));
|
||||
assert_eq!(Duration::days(i64::MAX / MICROS_PER_DAY + 1).num_microseconds(), None);
|
||||
assert_eq!(Duration::days(i64::MIN / MICROS_PER_DAY - 1).num_microseconds(), None);
|
||||
#[test] #[should_panic]
|
||||
fn sub_bad1() {
|
||||
Duration::new(0, 0) - Duration::new(0, 1);
|
||||
}
|
||||
|
||||
#[test] #[should_panic]
|
||||
fn sub_bad2() {
|
||||
Duration::new(0, 0) - Duration::new(1, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_duration_num_nanoseconds() {
|
||||
assert_eq!(Duration::zero().num_nanoseconds(), Some(0));
|
||||
assert_eq!(Duration::nanoseconds(1).num_nanoseconds(), Some(1));
|
||||
assert_eq!(Duration::nanoseconds(-1).num_nanoseconds(), Some(-1));
|
||||
assert_eq!(Duration::nanoseconds(i64::MAX).num_nanoseconds(), Some(i64::MAX));
|
||||
assert_eq!(Duration::nanoseconds(i64::MIN).num_nanoseconds(), Some(i64::MIN));
|
||||
assert_eq!(MAX.num_nanoseconds(), None);
|
||||
assert_eq!(MIN.num_nanoseconds(), None);
|
||||
|
||||
// overflow checks
|
||||
const NANOS_PER_DAY: i64 = 86400_000_000_000;
|
||||
assert_eq!(Duration::days(i64::MAX / NANOS_PER_DAY).num_nanoseconds(),
|
||||
Some(i64::MAX / NANOS_PER_DAY * NANOS_PER_DAY));
|
||||
assert_eq!(Duration::days(i64::MIN / NANOS_PER_DAY).num_nanoseconds(),
|
||||
Some(i64::MIN / NANOS_PER_DAY * NANOS_PER_DAY));
|
||||
assert_eq!(Duration::days(i64::MAX / NANOS_PER_DAY + 1).num_nanoseconds(), None);
|
||||
assert_eq!(Duration::days(i64::MIN / NANOS_PER_DAY - 1).num_nanoseconds(), None);
|
||||
fn mul() {
|
||||
assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2));
|
||||
assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3));
|
||||
assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4));
|
||||
assert_eq!(Duration::new(0, 500_000_001) * 4000,
|
||||
Duration::new(2000, 4000));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_duration_checked_ops() {
|
||||
assert_eq!(Duration::milliseconds(i64::MAX - 1).checked_add(&Duration::microseconds(999)),
|
||||
Some(Duration::milliseconds(i64::MAX - 2) + Duration::microseconds(1999)));
|
||||
assert!(Duration::milliseconds(i64::MAX).checked_add(&Duration::microseconds(1000))
|
||||
.is_none());
|
||||
|
||||
assert_eq!(Duration::milliseconds(i64::MIN).checked_sub(&Duration::milliseconds(0)),
|
||||
Some(Duration::milliseconds(i64::MIN)));
|
||||
assert!(Duration::milliseconds(i64::MIN).checked_sub(&Duration::milliseconds(1))
|
||||
.is_none());
|
||||
fn div() {
|
||||
assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0));
|
||||
assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333));
|
||||
assert_eq!(Duration::new(99, 999_999_000) / 100,
|
||||
Duration::new(0, 999_999_990));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_duration_mul() {
|
||||
assert_eq!(Duration::zero() * i32::MAX, Duration::zero());
|
||||
assert_eq!(Duration::zero() * i32::MIN, Duration::zero());
|
||||
assert_eq!(Duration::nanoseconds(1) * 0, Duration::zero());
|
||||
assert_eq!(Duration::nanoseconds(1) * 1, Duration::nanoseconds(1));
|
||||
assert_eq!(Duration::nanoseconds(1) * 1_000_000_000, Duration::seconds(1));
|
||||
assert_eq!(Duration::nanoseconds(1) * -1_000_000_000, -Duration::seconds(1));
|
||||
assert_eq!(-Duration::nanoseconds(1) * 1_000_000_000, -Duration::seconds(1));
|
||||
assert_eq!(Duration::nanoseconds(30) * 333_333_333,
|
||||
Duration::seconds(10) - Duration::nanoseconds(10));
|
||||
assert_eq!((Duration::nanoseconds(1) + Duration::seconds(1) + Duration::days(1)) * 3,
|
||||
Duration::nanoseconds(3) + Duration::seconds(3) + Duration::days(3));
|
||||
assert_eq!(Duration::milliseconds(1500) * -2, Duration::seconds(-3));
|
||||
assert_eq!(Duration::milliseconds(-1500) * 2, Duration::seconds(-3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_duration_div() {
|
||||
assert_eq!(Duration::zero() / i32::MAX, Duration::zero());
|
||||
assert_eq!(Duration::zero() / i32::MIN, Duration::zero());
|
||||
assert_eq!(Duration::nanoseconds(123_456_789) / 1, Duration::nanoseconds(123_456_789));
|
||||
assert_eq!(Duration::nanoseconds(123_456_789) / -1, -Duration::nanoseconds(123_456_789));
|
||||
assert_eq!(-Duration::nanoseconds(123_456_789) / -1, Duration::nanoseconds(123_456_789));
|
||||
assert_eq!(-Duration::nanoseconds(123_456_789) / 1, -Duration::nanoseconds(123_456_789));
|
||||
assert_eq!(Duration::seconds(1) / 3, Duration::nanoseconds(333_333_333));
|
||||
assert_eq!(Duration::seconds(4) / 3, Duration::nanoseconds(1_333_333_333));
|
||||
assert_eq!(Duration::seconds(-1) / 2, Duration::milliseconds(-500));
|
||||
assert_eq!(Duration::seconds(1) / -2, Duration::milliseconds(-500));
|
||||
assert_eq!(Duration::seconds(-1) / -2, Duration::milliseconds(500));
|
||||
assert_eq!(Duration::seconds(-4) / 3, Duration::nanoseconds(-1_333_333_333));
|
||||
assert_eq!(Duration::seconds(-4) / -3, Duration::nanoseconds(1_333_333_333));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_duration_fmt() {
|
||||
assert_eq!(Duration::zero().to_string(), "PT0S");
|
||||
assert_eq!(Duration::days(42).to_string(), "P42D");
|
||||
assert_eq!(Duration::days(-42).to_string(), "-P42D");
|
||||
assert_eq!(Duration::seconds(42).to_string(), "PT42S");
|
||||
assert_eq!(Duration::milliseconds(42).to_string(), "PT0.042S");
|
||||
assert_eq!(Duration::microseconds(42).to_string(), "PT0.000042S");
|
||||
assert_eq!(Duration::nanoseconds(42).to_string(), "PT0.000000042S");
|
||||
assert_eq!((Duration::days(7) + Duration::milliseconds(6543)).to_string(),
|
||||
"P7DT6.543S");
|
||||
assert_eq!(Duration::seconds(-86401).to_string(), "-P1DT1S");
|
||||
assert_eq!(Duration::nanoseconds(-1).to_string(), "-PT0.000000001S");
|
||||
|
||||
// the format specifier should have no effect on `Duration`
|
||||
assert_eq!(format!("{:30}", Duration::days(1) + Duration::milliseconds(2345)),
|
||||
"P1DT2.345S");
|
||||
fn display() {
|
||||
assert_eq!(Duration::new(0, 2).to_string(), "2ns");
|
||||
assert_eq!(Duration::new(0, 2_000_000).to_string(), "2ms");
|
||||
assert_eq!(Duration::new(2, 0).to_string(), "2s");
|
||||
assert_eq!(Duration::new(2, 2).to_string(), "2.000000002s");
|
||||
assert_eq!(Duration::new(2, 2_000_000).to_string(),
|
||||
"2.002s");
|
||||
assert_eq!(Duration::new(0, 2_000_002).to_string(),
|
||||
"2000002ns");
|
||||
assert_eq!(Duration::new(2, 2_000_002).to_string(),
|
||||
"2.002000002s");
|
||||
}
|
||||
}
|
||||
|
@ -10,17 +10,8 @@
|
||||
|
||||
//! Temporal quantification.
|
||||
|
||||
#![unstable(feature = "std_misc")]
|
||||
|
||||
use sys::time::SteadyTime;
|
||||
#![unstable(feature = "time")]
|
||||
|
||||
pub use self::duration::Duration;
|
||||
|
||||
pub mod duration;
|
||||
|
||||
/// Returns the current value of a high-resolution performance counter
|
||||
/// in nanoseconds since an unspecified epoch.
|
||||
// NB: this is intentionally not public, this is not ready to stabilize its api.
|
||||
fn precise_time_ns() -> u64 {
|
||||
SteadyTime::now().ns()
|
||||
}
|
||||
mod duration;
|
||||
|
@ -43,6 +43,8 @@
|
||||
#![feature(std_misc)]
|
||||
#![feature(libc)]
|
||||
#![feature(set_stdio)]
|
||||
#![feature(duration)]
|
||||
#![feature(duration_span)]
|
||||
|
||||
extern crate getopts;
|
||||
extern crate serialize;
|
||||
@ -1069,7 +1071,7 @@ impl Bencher {
|
||||
}
|
||||
|
||||
pub fn ns_elapsed(&mut self) -> u64 {
|
||||
self.dur.num_nanoseconds().unwrap() as u64
|
||||
self.dur.secs() * 1_000_000_000 + (self.dur.extra_nanos() as u64)
|
||||
}
|
||||
|
||||
pub fn ns_per_iter(&mut self) -> u64 {
|
||||
@ -1105,7 +1107,7 @@ impl Bencher {
|
||||
// (i.e. larger error bars).
|
||||
if n == 0 { n = 1; }
|
||||
|
||||
let mut total_run = Duration::nanoseconds(0);
|
||||
let mut total_run = Duration::new(0, 0);
|
||||
let samples : &mut [f64] = &mut [0.0_f64; 50];
|
||||
loop {
|
||||
let mut summ = None;
|
||||
@ -1134,7 +1136,7 @@ impl Bencher {
|
||||
|
||||
// If we've run for 100ms and seem to have converged to a
|
||||
// stable median.
|
||||
if loop_run.num_milliseconds() > 100 &&
|
||||
if loop_run > Duration::from_millis(100) &&
|
||||
summ.median_abs_dev_pct < 1.0 &&
|
||||
summ.median - summ5.median < summ5.median_abs_dev {
|
||||
return summ5;
|
||||
@ -1142,7 +1144,7 @@ impl Bencher {
|
||||
|
||||
total_run = total_run + loop_run;
|
||||
// Longest we ever run for is 3s.
|
||||
if total_run.num_seconds() > 3 {
|
||||
if total_run > Duration::from_secs(3) {
|
||||
return summ5;
|
||||
}
|
||||
|
||||
@ -1166,7 +1168,7 @@ pub mod bench {
|
||||
pub fn benchmark<F>(f: F) -> BenchSamples where F: FnMut(&mut Bencher) {
|
||||
let mut bs = Bencher {
|
||||
iterations: 0,
|
||||
dur: Duration::nanoseconds(0),
|
||||
dur: Duration::new(0, 0),
|
||||
bytes: 0
|
||||
};
|
||||
|
||||
@ -1185,7 +1187,7 @@ pub mod bench {
|
||||
pub fn run_once<F>(f: F) where F: FnOnce(&mut Bencher) {
|
||||
let mut bs = Bencher {
|
||||
iterations: 0,
|
||||
dur: Duration::nanoseconds(0),
|
||||
dur: Duration::new(0, 0),
|
||||
bytes: 0
|
||||
};
|
||||
bs.bench_n(1, f);
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(std_misc, rand)]
|
||||
#![feature(std_misc, rand, duration, duration_span)]
|
||||
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::env;
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// ignore-pretty very bad with line comments
|
||||
|
||||
#![feature(unboxed_closures, rand, std_misc, collections)]
|
||||
#![feature(unboxed_closures, rand, std_misc, collections, duration, duration_span)]
|
||||
|
||||
extern crate collections;
|
||||
extern crate rand;
|
||||
@ -167,13 +167,13 @@ fn write_results(label: &str, results: &Results) {
|
||||
|
||||
fn empty_results() -> Results {
|
||||
Results {
|
||||
sequential_ints: Duration::seconds(0),
|
||||
random_ints: Duration::seconds(0),
|
||||
delete_ints: Duration::seconds(0),
|
||||
sequential_ints: Duration::new(0, 0),
|
||||
random_ints: Duration::new(0, 0),
|
||||
delete_ints: Duration::new(0, 0),
|
||||
|
||||
sequential_strings: Duration::seconds(0),
|
||||
random_strings: Duration::seconds(0),
|
||||
delete_strings: Duration::seconds(0),
|
||||
sequential_strings: Duration::new(0, 0),
|
||||
random_strings: Duration::new(0, 0),
|
||||
delete_strings: Duration::new(0, 0),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// Microbenchmarks for various functions in std and extra
|
||||
|
||||
#![feature(rand, collections, std_misc)]
|
||||
#![feature(rand, collections, std_misc, duration, duration_span)]
|
||||
|
||||
use std::iter::repeat;
|
||||
use std::mem::swap;
|
||||
@ -52,7 +52,7 @@ fn maybe_run_test<F>(argv: &[String], name: String, test: F) where F: FnOnce() {
|
||||
|
||||
let dur = Duration::span(test);
|
||||
|
||||
println!("{}:\t\t{} ms", name, dur.num_milliseconds());
|
||||
println!("{}:\t\t{}", name, dur);
|
||||
}
|
||||
|
||||
fn shift_push() {
|
||||
|
@ -18,7 +18,7 @@
|
||||
// different scalability characteristics compared to the select
|
||||
// version.
|
||||
|
||||
#![feature(std_misc)]
|
||||
#![feature(duration, duration_span)]
|
||||
|
||||
use std::sync::mpsc::{channel, Sender, Receiver};
|
||||
use std::env;
|
||||
@ -88,9 +88,9 @@ fn run(args: &[String]) {
|
||||
});
|
||||
let result = result.unwrap();
|
||||
print!("Count is {}\n", result);
|
||||
print!("Test took {} ms\n", dur.num_milliseconds());
|
||||
let thruput = ((size / workers * workers) as f64) / (dur.num_milliseconds() as f64);
|
||||
print!("Throughput={} per sec\n", thruput / 1000.0);
|
||||
print!("Test took {}\n", dur);
|
||||
let thruput = ((size / workers * workers) as f64) / (dur.secs() as f64);
|
||||
print!("Throughput={} per sec\n", thruput);
|
||||
assert_eq!(result, num_bytes * size);
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
//
|
||||
// I *think* it's the same, more or less.
|
||||
|
||||
#![feature(std_misc)]
|
||||
#![feature(duration, duration_span)]
|
||||
|
||||
use std::sync::mpsc::{channel, Sender, Receiver};
|
||||
use std::env;
|
||||
@ -95,9 +95,9 @@ fn run(args: &[String]) {
|
||||
});
|
||||
let result = result.unwrap();
|
||||
print!("Count is {}\n", result);
|
||||
print!("Test took {} ms\n", dur.num_milliseconds());
|
||||
let thruput = ((size / workers * workers) as f64) / (dur.num_milliseconds() as f64);
|
||||
print!("Throughput={} per sec\n", thruput / 1000.0);
|
||||
print!("Test took {}\n", dur);
|
||||
let thruput = ((size / workers * workers) as f64) / (dur.secs() as f64);
|
||||
print!("Throughput={} per sec\n", thruput);
|
||||
assert_eq!(result, num_bytes * size);
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
// no-pretty-expanded FIXME #15189
|
||||
|
||||
#![feature(std_misc)]
|
||||
#![feature(duration, duration_span, std_misc)]
|
||||
|
||||
use std::env;
|
||||
use std::sync::{Arc, Future, Mutex, Condvar};
|
||||
@ -107,9 +107,9 @@ fn main() {
|
||||
|
||||
// all done, report stats.
|
||||
let num_msgs = num_tasks * msg_per_task;
|
||||
let rate = (num_msgs as f64) / (dur.num_milliseconds() as f64);
|
||||
let rate = (num_msgs as f64) / (dur.secs() as f64);
|
||||
|
||||
println!("Sent {} messages in {} ms", num_msgs, dur.num_milliseconds());
|
||||
println!(" {} messages / second", rate / 1000.0);
|
||||
println!(" {} μs / message", 1000000. / rate / 1000.0);
|
||||
println!("Sent {} messages in {}", num_msgs, dur);
|
||||
println!(" {} messages / second", rate);
|
||||
println!(" {} μs / message", 1000000. / rate);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
*/
|
||||
|
||||
#![feature(std_misc, rustc_private)]
|
||||
#![feature(duration, duration_span, rustc_private)]
|
||||
|
||||
extern crate getopts;
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// Microbenchmark for the smallintmap library
|
||||
|
||||
#![feature(collections, std_misc)]
|
||||
#![feature(collections, duration, duration_span)]
|
||||
|
||||
use std::collections::VecMap;
|
||||
use std::env;
|
||||
@ -40,8 +40,8 @@ fn main() {
|
||||
let max = args[1].parse::<usize>().unwrap();
|
||||
let rep = args[2].parse::<usize>().unwrap();
|
||||
|
||||
let mut checkf = Duration::seconds(0);
|
||||
let mut appendf = Duration::seconds(0);
|
||||
let mut checkf = Duration::new(0, 0);
|
||||
let mut appendf = Duration::new(0, 0);
|
||||
|
||||
for _ in 0..rep {
|
||||
let mut map = VecMap::new();
|
||||
@ -55,7 +55,7 @@ fn main() {
|
||||
let maxf = max as f64;
|
||||
|
||||
println!("insert(): {} seconds\n", checkf);
|
||||
println!(" : {} op/ms\n", maxf / checkf.num_milliseconds() as f64);
|
||||
println!(" : {} op/s\n", maxf / checkf.secs() as f64);
|
||||
println!("get() : {} seconds\n", appendf);
|
||||
println!(" : {} op/ms\n", maxf / appendf.num_milliseconds() as f64);
|
||||
println!(" : {} op/s\n", maxf / appendf.secs() as f64);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(box_syntax, std_misc, collections)]
|
||||
#![feature(box_syntax, duration, duration_span, collections)]
|
||||
|
||||
use std::env;
|
||||
use std::thread;
|
||||
|
@ -16,7 +16,7 @@
|
||||
// instead of in std.
|
||||
|
||||
#![reexport_test_harness_main = "test_main"]
|
||||
#![feature(libc, std_misc)]
|
||||
#![feature(libc, std_misc, duration)]
|
||||
|
||||
extern crate libc;
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// pretty-expanded FIXME #23616
|
||||
|
||||
#![feature(std_misc, alloc)]
|
||||
#![feature(std_misc, alloc, static_condvar)]
|
||||
|
||||
use std::sync;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user