fp_bindgen_support/guest/async/
mod.rs1mod queue;
2pub mod task;
3use crate::common::{
4 mem::{from_fat_ptr, FatPtr},
5 r#async::{AsyncValue, FUTURE_STATUS_PENDING, FUTURE_STATUS_READY},
6};
7use once_cell::unsync::Lazy;
8use std::collections::BTreeMap;
9use std::future::Future;
10use std::ptr::{read_volatile, write_volatile};
11use std::task::{Context, Poll, Waker};
12
13static mut WAKERS: Lazy<BTreeMap<FatPtr, Waker>> = Lazy::new(BTreeMap::new);
14
15pub struct HostFuture {
17 ptr: FatPtr,
18}
19
20impl HostFuture {
21 pub unsafe fn new(async_value_ptr: FatPtr) -> Self {
27 Self {
28 ptr: async_value_ptr,
29 }
30 }
31}
32
33impl Future for HostFuture {
34 type Output = FatPtr;
35
36 fn poll(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
37 let (ptr, _) = from_fat_ptr(self.ptr);
38 let async_value = unsafe { read_volatile(ptr as *const AsyncValue) };
39 match async_value.status {
40 FUTURE_STATUS_PENDING => {
41 unsafe {
42 WAKERS.insert(self.ptr, cx.waker().clone());
43 }
44 Poll::Pending
45 }
46 FUTURE_STATUS_READY => Poll::Ready(async_value.buffer_ptr()),
47 status => panic!("Unexpected status: {}", status),
48 }
49 }
50}
51
52#[doc(hidden)]
53#[no_mangle]
54pub unsafe fn __fp_guest_resolve_async_value(async_value_fat_ptr: FatPtr, result_ptr: FatPtr) {
55 let (ptr, len) = from_fat_ptr(result_ptr);
57 let (async_value_ptr, _) = from_fat_ptr(async_value_fat_ptr);
58 write_volatile(
59 async_value_ptr as *mut AsyncValue,
60 AsyncValue {
61 status: FUTURE_STATUS_READY,
62 ptr: ptr as u32,
63 len,
64 },
65 );
66
67 if let Some(waker) = WAKERS.remove(&async_value_fat_ptr) {
68 waker.wake();
69 }
70}
71
72#[link(wasm_import_module = "fp")]
73extern "C" {
74 fn __fp_host_resolve_async_value(async_value_ptr: FatPtr, result_ptr: FatPtr);
75}
76
77pub fn host_resolve_async_value(async_value_ptr: FatPtr, result_ptr: FatPtr) {
78 unsafe { __fp_host_resolve_async_value(async_value_ptr, result_ptr) }
79}