#![no_std]
#[cfg(not(feature = "no_std"))]
extern crate std;
extern crate alloc;
mod runtime;
pub use runtime::*;
mod defer;
#[cfg(not(feature = "no_std"))]
pub use defer::*;
mod yielding;
pub use yielding::*;
mod joiner;
pub use joiner::*;
use alloc::boxed::Box;
use core::pin::Pin;
use core::{cell::RefCell, future::Future};
use core::{mem, mem::ManuallyDrop, panic};
pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>;
#[inline]
pub fn prep<'a, T>(future: impl Future<Output = T> + 'a + Send) -> BoxFuture<'a, T> {
Box::pin(future)
}
#[cfg(feature = "no_std")]
mod no_std_util {
pub struct ForceShare<T>(pub T);
unsafe impl<T> Send for ForceShare<T> {}
unsafe impl<T> Sync for ForceShare<T> {}
impl<T> ForceShare<T> {
pub fn with<F, R>(&self, fun: F) -> R
where
F: FnOnce(&T) -> R,
{
fun(&self.0)
}
}
}
#[cfg(feature = "no_std")]
static CURRENT_RUNTIME: no_std_util::ForceShare<
RefCell<Option<ManuallyDrop<Box<dyn InternalRuntime>>>>,
> = no_std_util::ForceShare(RefCell::new(None));
#[cfg(not(feature = "no_std"))]
std::thread_local! {
static CURRENT_RUNTIME: RefCell<Option<ManuallyDrop<Box<dyn InternalRuntime>>>> = RefCell::new(None);
}
pub async fn get_current_runtime<'a>() -> RuntimeWrapper<'a> {
CURRENT_RUNTIME.with(|x| {
if let Some(x) = x.borrow_mut().as_mut() {
unsafe { RuntimeWrapper(&mut *(x.as_mut() as *mut _)) }
} else {
panic!(
"get_current_runtime MUST only be called from a future running within a Runtime!"
)
}
})
}
pub fn set_current_runtime(runtime: &mut dyn InternalRuntime) {
CURRENT_RUNTIME.with(move |x| {
*x.borrow_mut() = Some(unsafe {
ManuallyDrop::new(Box::from_raw(
mem::transmute::<_, *mut dyn InternalRuntime>(runtime),
))
})
})
}
pub fn clear_current_runtime() {
CURRENT_RUNTIME.with(|x| *x.borrow_mut() = None)
}