diff options
Diffstat (limited to 'src/libstd/time.rs')
| -rw-r--r-- | src/libstd/time.rs | 67 |
1 files changed, 56 insertions, 11 deletions
diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 63cede79e48..507ea395c6c 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -1,13 +1,3 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - //! Temporal quantification. //! //! Example: @@ -22,15 +12,20 @@ #![stable(feature = "time", since = "1.3.0")] +use cmp; use error::Error; use fmt; use ops::{Add, Sub, AddAssign, SubAssign}; use sys::time; use sys_common::FromInner; +use sys_common::mutex::Mutex; #[stable(feature = "time", since = "1.3.0")] pub use core::time::Duration; +#[unstable(feature = "duration_constants", issue = "57391")] +pub use core::time::{SECOND, MILLISECOND, MICROSECOND, NANOSECOND}; + /// A measurement of a monotonically nondecreasing clock. /// Opaque and useful only with `Duration`. /// @@ -160,7 +155,45 @@ impl Instant { /// ``` #[stable(feature = "time2", since = "1.8.0")] pub fn now() -> Instant { - Instant(time::Instant::now()) + let os_now = time::Instant::now(); + + // And here we come upon a sad state of affairs. The whole point of + // `Instant` is that it's monotonically increasing. We've found in the + // wild, however, that it's not actually monotonically increasing for + // one reason or another. These appear to be OS and hardware level bugs, + // and there's not really a whole lot we can do about them. Here's a + // taste of what we've found: + // + // * #48514 - OpenBSD, x86_64 + // * #49281 - linux arm64 and s390x + // * #51648 - windows, x86 + // * #56560 - windows, x86_64, AWS + // * #56612 - windows, x86, vm (?) + // * #56940 - linux, arm64 + // * https://bugzilla.mozilla.org/show_bug.cgi?id=1487778 - a similar + // Firefox bug + // + // It simply seems that this it just happens so that a lot in the wild + // we're seeing panics across various platforms where consecutive calls + // to `Instant::now`, such as via the `elapsed` function, are panicking + // as they're going backwards. Placed here is a last-ditch effort to try + // to fix things up. We keep a global "latest now" instance which is + // returned instead of what the OS says if the OS goes backwards. + // + // To hopefully mitigate the impact of this though a few platforms are + // whitelisted as "these at least haven't gone backwards yet". + if time::Instant::actually_monotonic() { + return Instant(os_now) + } + + static LOCK: Mutex = Mutex::new(); + static mut LAST_NOW: time::Instant = time::Instant::zero(); + unsafe { + let _lock = LOCK.lock(); + let now = cmp::max(LAST_NOW, os_now); + LAST_NOW = now; + Instant(now) + } } /// Returns the amount of time elapsed from another instant to this one. @@ -230,6 +263,12 @@ impl Instant { impl Add<Duration> for Instant { type Output = Instant; + /// # Panics + /// + /// This function may panic if the resulting point in time cannot be represented by the + /// underlying data structure. See [`checked_add`] for a version without panic. + /// + /// [`checked_add`]: ../../std/time/struct.Instant.html#method.checked_add fn add(self, other: Duration) -> Instant { self.checked_add(other) .expect("overflow when adding duration to instant") @@ -397,6 +436,12 @@ impl SystemTime { impl Add<Duration> for SystemTime { type Output = SystemTime; + /// # Panics + /// + /// This function may panic if the resulting point in time cannot be represented by the + /// underlying data structure. See [`checked_add`] for a version without panic. + /// + /// [`checked_add`]: ../../std/time/struct.SystemTime.html#method.checked_add fn add(self, dur: Duration) -> SystemTime { self.checked_add(dur) .expect("overflow when adding duration to instant") |
