use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
pub mod internals;
pub fn spawn<F: 'static + Future<Output = ()>>(future: F) {
pin_project_lite::pin_project! {
struct ProtectedTask<F> {
#[pin]
future: F,
completed: bool,
}
impl<F> PinnedDrop for ProtectedTask<F> {
#[track_caller]
fn drop(this: Pin<&mut Self>) {
if !this.completed && !ic_cdk_executor::is_recovering_from_trap() {
panic!("protected task outlived its canister method (did you mean to use spawn_weak or spawn_migratory?)")
}
}
}
}
impl<F> Future for ProtectedTask<F>
where
F: Future<Output = ()>,
{
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.project();
let res = this.future.poll(cx);
if res.is_ready() {
*this.completed = true;
}
res
}
}
ic_cdk_executor::spawn_protected(ProtectedTask {
future,
completed: false,
});
}
pub fn spawn_weak<F: 'static + Future<Output = ()>>(future: F) {
ic_cdk_executor::spawn_protected(future);
}
pub fn spawn_migratory<F: 'static + Future<Output = ()>>(future: F) {
ic_cdk_executor::spawn_migratory(future);
}
pub fn is_recovering_from_trap() -> bool {
ic_cdk_executor::is_recovering_from_trap()
}