#[link(wasm_import_module = "$root")]
unsafe extern "C" {
#[link_name = "[waitable-set-new]"]
fn set_new() -> u32;
#[link_name = "[waitable-set-drop]"]
fn set_drop(set: u32);
#[link_name = "[waitable-join]"]
fn raw_join(waitable: u32, set: u32);
#[link_name = "[waitable-set-wait]"]
fn wait(set: u32, payload: *mut [u32; 2]) -> u32;
#[link_name = "[waitable-set-poll]"]
fn poll(set: u32, payload: *mut [u32; 2]) -> u32;
#[link_name = "[subtask-cancel]"]
pub(super) fn raw_subtask_cancel(task: u32) -> u32;
#[link_name = "[subtask-drop]"]
pub(super) fn raw_subtask_drop(task: u32);
}
pub struct WaitSet(u32);
impl WaitSet {
pub fn new() -> Self {
Self(unsafe { set_new() })
}
pub fn join(&self, waitable: u32) {
unsafe {
super::abi::preserving_stack(|| raw_join(waitable, self.0));
}
}
pub fn remove(&self, waitable: u32) {
unsafe {
super::abi::preserving_stack(|| raw_join(waitable, 0));
}
}
pub fn step(&self, blocking: bool) -> (u32, u32, u32) {
let mut payload = [0; 2];
let kind = super::abi::preserving_stack(|| unsafe {
if blocking {
wait(self.0, &mut payload)
} else {
poll(self.0, &mut payload)
}
});
(kind, payload[0], payload[1])
}
}
impl Drop for WaitSet {
fn drop(&mut self) {
unsafe {
set_drop(self.0);
}
}
}
pub(super) unsafe fn subtask_cancel(task: u32) -> u32 {
super::abi::preserving_stack(|| unsafe { raw_subtask_cancel(task) })
}
pub(super) unsafe fn subtask_drop(task: u32) {
super::abi::preserving_stack(|| unsafe { raw_subtask_drop(task) })
}