#![no_std]
#[cfg(any(
feature = "async-executor",
feature = "compio",
feature = "dioxus",
feature = "futures-executor",
feature = "tokio",
feature = "wasm-bindgen",
))]
extern crate alloc;
use core::{alloc::Layout, future::Future};
#[cfg(feature = "dioxus")]
pub use dioxus::DioxusSpawner;
#[cfg(feature = "wasm-bindgen")]
pub use wasm_bindgen::WasmBindgenSpawner;
#[cfg(feature = "async-executor")]
mod async_executor;
#[cfg(feature = "compio")]
mod compio;
#[cfg(feature = "dioxus")]
mod dioxus;
#[cfg(feature = "futures-executor")]
mod futures_executor;
#[cfg(feature = "tokio")]
mod tokio;
#[cfg(feature = "wasm-bindgen")]
mod wasm_bindgen;
#[derive(Debug)]
pub enum SpawnError {
Shutdown,
Other,
}
pub type Result<T> = core::result::Result<T, SpawnError>;
pub struct LocalSpawner {
handle: *const (),
vtable: &'static LocalSpawnerVtable,
}
impl LocalSpawner {
pub fn new<T: IntoLocalSpawner>(inner: T) -> Self {
Self {
handle: unsafe { T::into_handle(inner) } as *const (),
vtable: LocalSpawnerVtable::get::<T>(),
}
}
pub fn spawn<F: Future<Output = ()> + 'static>(&self, f: F) -> Result<()> {
let builder = SpawnCompleterBuilder {
handle: self.handle,
vtable: self.vtable,
};
unsafe {
let spawn_completer = (self.vtable.spawn_dyn)(self.handle, builder, Layout::new::<F>());
spawn_completer.spawn(f)
}
}
}
impl Clone for LocalSpawner {
fn clone(&self) -> Self {
unsafe {
(self.vtable.on_clone)(self.handle);
}
Self {
handle: self.handle,
vtable: self.vtable,
}
}
}
impl Drop for LocalSpawner {
fn drop(&mut self) {
unsafe {
(self.vtable.on_drop)(self.handle);
}
}
}
pub trait IntoLocalSpawner {
unsafe fn into_handle(self) -> *const ();
unsafe fn spawn_dyn(
handle: *const (),
builder: SpawnCompleterBuilder,
future_layout: Layout,
) -> SpawnCompleter;
unsafe fn finish_spawn(
handle: *const (),
task_ptr_as_dyn_future: *mut dyn Future<Output = ()>,
) -> Result<()>;
unsafe fn on_clone(handle: *const ());
unsafe fn on_drop(handle: *const ());
}
pub struct SpawnCompleter {
handle: *const (),
vtable: &'static LocalSpawnerVtable,
task_ptr: *mut (),
future_ptr: *mut (),
}
pub struct SpawnCompleterBuilder {
handle: *const (),
vtable: &'static LocalSpawnerVtable,
}
impl SpawnCompleterBuilder {
pub fn build(self, task_ptr: *mut (), future_ptr: *mut ()) -> SpawnCompleter {
SpawnCompleter {
handle: self.handle,
vtable: self.vtable,
task_ptr,
future_ptr,
}
}
}
impl SpawnCompleter {
unsafe fn spawn<F: Future<Output = ()> + 'static>(self, f: F) -> Result<()> {
unsafe {
core::ptr::write(self.future_ptr as *mut F, f);
(self.vtable.finish_spawn)(
self.handle,
self.task_ptr as *mut F as *mut dyn Future<Output = ()>,
)
}
}
}
struct LocalSpawnerVtable {
spawn_dyn: unsafe fn(
handle: *const (),
builder: SpawnCompleterBuilder,
future_layout: Layout,
) -> SpawnCompleter,
finish_spawn: unsafe fn(
handle: *const (),
task_ptr_as_dyn_future: *mut dyn Future<Output = ()>,
) -> Result<()>,
on_clone: unsafe fn(handle: *const ()),
on_drop: unsafe fn(handle: *const ()),
}
impl LocalSpawnerVtable {
fn get<T: IntoLocalSpawner>() -> &'static Self {
&LocalSpawnerVtable {
spawn_dyn: T::spawn_dyn,
finish_spawn: T::finish_spawn,
on_clone: T::on_clone,
on_drop: T::on_drop,
}
}
}