cfg_not_test_util! {
use crate::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub(crate) struct Clock {}
pub(crate) fn now() -> Instant {
Instant::from_std(std::time::Instant::now())
}
impl Clock {
pub(crate) fn new() -> Clock {
Clock {}
}
pub(crate) fn now(&self) -> Instant {
now()
}
pub(crate) fn is_paused(&self) -> bool {
false
}
pub(crate) fn advance(&self, _dur: Duration) {
unreachable!();
}
}
}
cfg_test_util! {
use crate::time::{Duration, Instant};
use std::sync::{Arc, Mutex};
use crate::runtime::context;
#[derive(Debug, Clone)]
pub(crate) struct Clock {
inner: Arc<Mutex<Inner>>,
}
#[derive(Debug)]
struct Inner {
base: std::time::Instant,
unfrozen: Option<std::time::Instant>,
}
pub fn pause() {
let clock = context::clock().expect("time cannot be frozen from outside the Tokio runtime");
clock.pause();
}
pub fn resume() {
let clock = context::clock().expect("time cannot be frozen from outside the Tokio runtime");
let mut inner = clock.inner.lock().unwrap();
if inner.unfrozen.is_some() {
panic!("time is not frozen");
}
inner.unfrozen = Some(std::time::Instant::now());
}
pub async fn advance(duration: Duration) {
let clock = context::clock().expect("time cannot be frozen from outside the Tokio runtime");
clock.advance(duration);
crate::task::yield_now().await;
}
pub(crate) fn now() -> Instant {
if let Some(clock) = context::clock() {
clock.now()
} else {
Instant::from_std(std::time::Instant::now())
}
}
impl Clock {
pub(crate) fn new() -> Clock {
let now = std::time::Instant::now();
Clock {
inner: Arc::new(Mutex::new(Inner {
base: now,
unfrozen: Some(now),
})),
}
}
pub(crate) fn pause(&self) {
let mut inner = self.inner.lock().unwrap();
let elapsed = inner.unfrozen.as_ref().expect("time is already frozen").elapsed();
inner.base += elapsed;
inner.unfrozen = None;
}
pub(crate) fn is_paused(&self) -> bool {
let inner = self.inner.lock().unwrap();
inner.unfrozen.is_none()
}
pub(crate) fn advance(&self, duration: Duration) {
let mut inner = self.inner.lock().unwrap();
if inner.unfrozen.is_some() {
panic!("time is not frozen");
}
inner.base += duration;
}
pub(crate) fn now(&self) -> Instant {
let inner = self.inner.lock().unwrap();
let mut ret = inner.base;
if let Some(unfrozen) = inner.unfrozen {
ret += unfrozen.elapsed();
}
Instant::from_std(ret)
}
}
}