use clock::Now;
use timer;
use tokio_executor::Enter;
use std::cell::RefCell;
use std::fmt;
use std::sync::Arc;
use std::time::Instant;
#[derive(Default, Clone)]
pub struct Clock {
now: Option<Arc<dyn Now>>,
}
#[derive(Debug)]
pub struct DefaultGuard {
_p: (),
}
thread_local! {
static CLOCK: RefCell<Option<Clock>> = RefCell::new(None)
}
pub fn now() -> Instant {
CLOCK.with(|current| match current.borrow().as_ref() {
Some(c) => c.now(),
None => Instant::now(),
})
}
impl Clock {
pub fn new() -> Clock {
CLOCK.with(|current| match current.borrow().as_ref() {
Some(c) => c.clone(),
None => Clock::system(),
})
}
pub fn new_with_now<T: Now>(now: T) -> Clock {
Clock {
now: Some(Arc::new(now)),
}
}
pub fn system() -> Clock {
Clock { now: None }
}
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()
}
}
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)
}
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());
}
}