use super::timer::*;
use super::*;
use once_cell::sync::Lazy;
use std::sync::Arc;
static TIMER_MANAGER: Lazy<Arc<TimerManager>> = Lazy::new(|| {
let tm = Arc::new(TimerManager::new());
check_clock_thread(&tm);
tm
});
fn check_clock_thread(tm: &Arc<TimerManager>) {
if tm.should_i_start_clock() {
std::thread::Builder::new()
.name("Timer thread".into())
.spawn(|| TIMER_MANAGER.clock_thread())
.unwrap();
}
}
pub struct FastTimeout(Duration);
impl ToTimeout for FastTimeout {
fn timeout(&self) -> Pin<Box<dyn Future<Output = ()> + Send + Sync>> {
Box::pin(TIMER_MANAGER.register_timer(self.0).poll())
}
fn create(d: Duration) -> Self {
FastTimeout(d)
}
}
pub fn fast_timeout<T>(duration: Duration, future: T) -> Timeout<T, FastTimeout>
where
T: Future,
{
check_clock_thread(&TIMER_MANAGER);
Timeout::new_with_delay(future, duration)
}
pub async fn fast_sleep(duration: Duration) {
check_clock_thread(&TIMER_MANAGER);
TIMER_MANAGER.register_timer(duration).poll().await
}
pub fn pause_for_fork() {
TIMER_MANAGER.pause_for_fork();
}
pub fn unpause() {
TIMER_MANAGER.unpause();
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_timeout() {
let fut = tokio_sleep(Duration::from_secs(1000));
let to = fast_timeout(Duration::from_secs(1), fut);
assert!(to.await.is_err())
}
#[tokio::test]
async fn test_instantly_return() {
let fut = async { 1 };
let to = fast_timeout(Duration::from_secs(1), fut);
assert_eq!(to.await.unwrap(), 1)
}
#[tokio::test]
async fn test_delayed_return() {
let fut = async {
tokio_sleep(Duration::from_secs(1)).await;
1
};
let to = fast_timeout(Duration::from_secs(1000), fut);
assert_eq!(to.await.unwrap(), 1)
}
#[tokio::test]
async fn test_sleep() {
let fut = async {
fast_sleep(Duration::from_secs(1)).await;
1
};
let to = fast_timeout(Duration::from_secs(1000), fut);
assert_eq!(to.await.unwrap(), 1)
}
}