Another attempt at abstracting Instant::now (#381)

Currently, the timer uses a `Now` trait to abstract the source of time.
This allows time to be mocked out. However, the current implementation
has a number of limitations as represented by #288 and #296.

The main issues are that `Now` requires `&mut self` which prevents a
value from being easily used in a concurrent environment. Also, when
wanting to write code that is abstract over the source of time, generics
get out of hand.

This patch provides an alternate solution. A new type, `Clock` is
provided which defaults to `Instant::now` as the source of time, but
allows configuring the actual source using a new iteration of the `Now`
trait. This time, `Now` is `Send + Sync + 'static`. Internally, `Clock`
stores the now value in an `Arc<Now>` value, which introduces dynamism
and allows `Clock` values to be cloned and be `Sync`.

Also, the current clock can be set for the current execution context
using the `with_default` pattern.

Because using the `Instant::now` will be the most common case by far, it
is special cased in order to avoid the need to allocate an `Arc` and use
dynamic dispatch.
This commit is contained in:
Carl Lerche
2018-06-06 16:04:39 -07:00
committed by GitHub
parent 9013ed9bd4
commit db620b42ec
15 changed files with 467 additions and 52 deletions
+3
View File
@@ -27,6 +27,9 @@
//! [`Now`]: trait.Now.html
//! [`Now::now`]: trait.Now.html#method.now
// This allows the usage of the old `Now` trait.
#![allow(deprecated)]
mod entry;
mod handle;
mod level;
+3 -20
View File
@@ -1,27 +1,10 @@
use std::time::Instant;
/// Returns `Instant` values representing the current instant in time.
///
/// This allows customizing the source of time which is especially useful for
/// testing.
#[doc(hidden)]
#[deprecated(since = "0.2.4", note = "use clock::Now instead")]
pub trait Now {
/// Returns an instant corresponding to "now".
fn now(&mut self) -> Instant;
}
/// Returns the instant corresponding to now using a monotonic clock.
#[derive(Debug)]
pub struct SystemNow(());
impl SystemNow {
/// Create a new `SystemNow`.
pub fn new() -> SystemNow {
SystemNow(())
}
}
impl Now for SystemNow {
fn now(&mut self) -> Instant {
Instant::now()
}
}
pub use ::clock::Clock as SystemNow;