use super::{AsyncSignaler, RuntimeSignaler};
use std::sync::Arc;
fn run<F: std::future::Future>(fut: F) -> F::Output {
#[cfg(feature = "tokio")]
{
::tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.expect("rt")
.block_on(fut)
}
#[cfg(all(feature = "smol", not(feature = "tokio")))]
{
::async_io::block_on(fut)
}
}
#[test]
fn signal_then_await_returns_immediately() {
run(async {
let s = Arc::new(RuntimeSignaler::new().expect("signaler"));
s.signal();
s.signaled().await;
});
}
#[test]
fn await_then_signal_wakes() {
run(async {
let s = Arc::new(RuntimeSignaler::new().expect("signaler"));
let s2 = Arc::clone(&s);
let waiter = async move { s2.signaled().await };
let firer = async move {
for _ in 0..16 {
#[cfg(feature = "tokio")]
::tokio::task::yield_now().await;
#[cfg(all(feature = "smol", not(feature = "tokio")))]
::smol::future::yield_now().await;
}
s.signal();
};
::futures::future::join(waiter, firer).await;
});
}
#[test]
fn coalesces_multiple_signals_into_one_wake() {
run(async {
let s = Arc::new(RuntimeSignaler::new().expect("signaler"));
for _ in 0..1000 {
s.signal();
}
s.signaled().await;
let s2 = Arc::clone(&s);
let waiter = async move { s2.signaled().await };
let firer = async move {
for _ in 0..16 {
#[cfg(feature = "tokio")]
::tokio::task::yield_now().await;
#[cfg(all(feature = "smol", not(feature = "tokio")))]
::smol::future::yield_now().await;
}
s.signal();
};
::futures::future::join(waiter, firer).await;
});
}
#[test]
fn cross_thread_signal_wakes_runtime_task() {
run(async {
let s = Arc::new(RuntimeSignaler::new().expect("signaler"));
let s_thread = Arc::clone(&s);
let _h = std::thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_millis(10));
s_thread.signal();
});
s.signaled().await;
});
}