use std::future::Future;
use std::net::IpAddr;
use std::time::Duration;
use tokio::task::LocalSet;
use tokio::time::sleep;
use crate::{KernelConfig, Net};
const NO_ADDRS: [IpAddr; 0] = [];
pub(crate) const TICK: Duration = Duration::from_millis(1);
mod client_server;
mod scheduler;
pub use client_server::ClientServer;
pub(crate) use scheduler::Scheduler;
pub fn lo<Fut>(fut: Fut) -> Fut::Output
where
Fut: Future + 'static,
Fut::Output: 'static,
{
lo_with_config(KernelConfig::default(), fut)
}
pub fn lo_with_config<Fut>(cfg: KernelConfig, fut: Fut) -> Fut::Output
where
Fut: Future + 'static,
Fut::Output: 'static,
{
let rt = tokio::runtime::Builder::new_current_thread()
.enable_time()
.start_paused(true)
.build()
.expect("build current_thread runtime");
let mut net = Net::with_config(cfg);
net.add_host(NO_ADDRS);
let guard = net.enter();
let guard_ref = &guard;
let result = rt.block_on(async {
let set = LocalSet::new();
let handle = set.spawn_local(fut);
let mut scheduler = Scheduler::new();
loop {
set.run_until(sleep(TICK)).await;
scheduler.tick(guard_ref, TICK);
if handle.is_finished() {
break handle.await.unwrap();
}
}
});
drop(guard);
result
}