use core::{
future::Future,
marker::PhantomData,
};
use tracing::error;
use crate::reactor::{
Reactor,
REACTOR,
};
pub struct Scope<'scope, 'env: 'scope> {
_scope: PhantomData<fn(&'scope ())>,
_env: PhantomData<&'env ()>,
}
impl<'scope, 'env> Scope<'scope, 'env> {
pub fn spawn<F>(&self, future: F)
where
F: Future<Output = ()> + 'scope,
{
unsafe { Reactor::spawn_unchecked(&REACTOR, future) };
}
}
pub fn scope<'env, F, T>(f: F) -> T
where
F: for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> T,
{
let ret = f(&Scope {
_scope: PhantomData,
_env: PhantomData,
});
if let Err(err) = crate::run() {
error!("failed to run in scope: {err}");
crate::freeze();
}
ret
}
#[cfg(test)]
mod tests {
use core::cell::RefCell;
use crate::DelayType;
#[test]
fn scoped() {
let done = RefCell::new(false);
super::scope(|scope| {
scope.spawn(async {
crate::delay(
lx::timespec {
tv_sec: 0,
tv_nsec: 1_000_000 * 200,
},
DelayType::Relative,
)
.await
.unwrap();
*done.borrow_mut() = true;
});
});
assert!(*done.borrow());
}
}