diff options
Diffstat (limited to 'third_party/rust/tokio-timer/src/clock/clock.rs')
-rw-r--r-- | third_party/rust/tokio-timer/src/clock/clock.rs | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/third_party/rust/tokio-timer/src/clock/clock.rs b/third_party/rust/tokio-timer/src/clock/clock.rs new file mode 100644 index 0000000000..2920e2817f --- /dev/null +++ b/third_party/rust/tokio-timer/src/clock/clock.rs @@ -0,0 +1,150 @@ +use clock::Now; +use timer; + +use tokio_executor::Enter; + +use std::cell::RefCell; +use std::fmt; +use std::sync::Arc; +use std::time::Instant; + +/// A handle to a source of time. +/// +/// `Clock` instances return [`Instant`] values corresponding to "now". The source +/// of these values is configurable. The default source is [`Instant::now`]. +/// +/// [`Instant`]: https://doc.rust-lang.org/std/time/struct.Instant.html +/// [`Instant::now`]: https://doc.rust-lang.org/std/time/struct.Instant.html#method.now +#[derive(Default, Clone)] +pub struct Clock { + now: Option<Arc<dyn Now>>, +} + +/// A guard that resets the current `Clock` to `None` when dropped. +#[derive(Debug)] +pub struct DefaultGuard { + _p: (), +} + +thread_local! { + /// Thread-local tracking the current clock + static CLOCK: RefCell<Option<Clock>> = RefCell::new(None) +} + +/// Returns an `Instant` corresponding to "now". +/// +/// This function delegates to the source of time configured for the current +/// execution context. By default, this is `Instant::now()`. +/// +/// Note that, because the source of time is configurable, it is possible to +/// observe non-monotonic behavior when calling `now` from different +/// executors. +/// +/// See [module](index.html) level documentation for more details. +/// +/// # Examples +/// +/// ``` +/// # use tokio_timer::clock; +/// let now = clock::now(); +/// ``` +pub fn now() -> Instant { + CLOCK.with(|current| match current.borrow().as_ref() { + Some(c) => c.now(), + None => Instant::now(), + }) +} + +impl Clock { + /// Return a new `Clock` instance that uses the current execution context's + /// source of time. + pub fn new() -> Clock { + CLOCK.with(|current| match current.borrow().as_ref() { + Some(c) => c.clone(), + None => Clock::system(), + }) + } + + /// Return a new `Clock` instance that uses `now` as the source of time. + pub fn new_with_now<T: Now>(now: T) -> Clock { + Clock { + now: Some(Arc::new(now)), + } + } + + /// Return a new `Clock` instance that uses [`Instant::now`] as the source + /// of time. + /// + /// [`Instant::now`]: https://doc.rust-lang.org/std/time/struct.Instant.html#method.now + pub fn system() -> Clock { + Clock { now: None } + } + + /// Returns an instant corresponding to "now" by using the instance's source + /// of time. + pub fn now(&self) -> Instant { + match self.now { + Some(ref now) => now.now(), + None => Instant::now(), + } + } +} + +#[allow(deprecated)] +impl timer::Now for Clock { + fn now(&mut self) -> Instant { + Clock::now(self) + } +} + +impl fmt::Debug for Clock { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("Clock") + .field("now", { + if self.now.is_some() { + &"Some(Arc<Now>)" + } else { + &"None" + } + }) + .finish() + } +} + +/// Set the default clock for the duration of the closure. +/// +/// # Panics +/// +/// This function panics if there already is a default clock set. +pub fn with_default<F, R>(clock: &Clock, enter: &mut Enter, f: F) -> R +where + F: FnOnce(&mut Enter) -> R, +{ + let _guard = set_default(clock); + + f(enter) +} + +/// Sets `clock` as the default clock, returning a guard that unsets it on drop. +/// +/// # Panics +/// +/// This function panics if there already is a default clock set. +pub fn set_default(clock: &Clock) -> DefaultGuard { + CLOCK.with(|cell| { + assert!( + cell.borrow().is_none(), + "default clock already set for execution context" + ); + + *cell.borrow_mut() = Some(clock.clone()); + + DefaultGuard { _p: () } + }) +} + +impl Drop for DefaultGuard { + fn drop(&mut self) { + let _ = CLOCK.try_with(|cell| cell.borrow_mut().take()); + } +} |