MCPcopy Create free account
hub / github.com/bytecodealliance/wasmtime / first_poll

Method first_poll

crates/wasmtime/src/runtime/component/concurrent.rs:2995–3112  ·  view source on GitHub ↗

Poll the specified future once on behalf of a guest->host call using an async-lowered import. If it returns `Ready`, return `Ok(None)`. Otherwise, if it returns `Pending`, add it to the set of futures to be polled as part of this instance's event loop until it completes, and then return `Ok(Some(handle))` where `handle` is the waitable handle to return. Whether the future returns `Ready` immedi

(
        self,
        mut store: StoreContextMut<'_, T>,
        future: impl Future<Output = Result<R>> + Send + 'static,
        lower: impl FnOnce(StoreContextMut<T>, Option<R>) -> Result<()> + S

Source from the content-addressed store, hash-verified

2993 /// stack and linear memory. The `lower` function is invoked with `None` if
2994 /// the future is cancelled.
2995 pub(crate) fn first_poll<T: 'static, R: Send + 'static>(
2996 self,
2997 mut store: StoreContextMut<'_, T>,
2998 future: impl Future<Output = Result<R>> + Send + 'static,
2999 lower: impl FnOnce(StoreContextMut<T>, Option<R>) -> Result<()> + Send + 'static,
3000 ) -> Result<Option<u32>> {
3001 let token = StoreToken::new(store.as_context_mut());
3002 let state = store.0.concurrent_state_mut();
3003 let task = state.current_host_thread()?;
3004
3005 // Create an abortable future which hooks calls to poll and manages call
3006 // context state for the future.
3007 let (join_handle, future) = JoinHandle::run(future);
3008 {
3009 let state = &mut state.get_mut(task)?.state;
3010 assert!(matches!(state, HostTaskState::CalleeStarted));
3011 *state = HostTaskState::CalleeRunning(join_handle);
3012 }
3013
3014 let mut future = Box::pin(future);
3015
3016 // Finally, poll the future. We can use a dummy `Waker` here because
3017 // we'll add the future to `ConcurrentState::futures` and poll it
3018 // automatically from the event loop if it doesn't complete immediately
3019 // here.
3020 let poll = tls::set(store.0, || {
3021 future
3022 .as_mut()
3023 .poll(&mut Context::from_waker(&Waker::noop()))
3024 });
3025
3026 match poll {
3027 // It finished immediately; lower the result and delete the task.
3028 Poll::Ready(result) => {
3029 let result = result.transpose()?;
3030 lower(store.as_context_mut(), result)?;
3031 return Ok(None);
3032 }
3033
3034 // Future isn't ready yet, so fall through.
3035 Poll::Pending => {}
3036 }
3037
3038 // It hasn't finished yet; add the future to
3039 // `ConcurrentState::futures` so it will be polled by the event
3040 // loop and allocate a waitable handle to return to the guest.
3041
3042 // Wrap the future in a closure responsible for lowering the result into
3043 // the guest's stack and memory, as well as notifying any waiters that
3044 // the task returned.
3045 let future = Box::pin(async move {
3046 let result = match future.await {
3047 Some(result) => Some(result?),
3048 None => None,
3049 };
3050 let on_complete = move |store: &mut dyn VMStore| {
3051 // Restore the `current_thread` to be the host so `lower` knows
3052 // how to manipulate borrows and knows which scope of borrows

Callers 1

call_async_lowerMethod · 0.80

Calls 15

OkFunction · 0.85
concurrent_state_mutMethod · 0.80
current_host_threadMethod · 0.80
set_threadMethod · 0.80
push_high_priorityMethod · 0.80
push_futureMethod · 0.80
subtask_insert_hostMethod · 0.80
handle_tableMethod · 0.80
newFunction · 0.50
runFunction · 0.50
setFunction · 0.50
lowerFunction · 0.50

Tested by

no test coverage detected