some_executor 0.7.1

A trait for libraries that abstract over any executor
Documentation
// SPDX-License-Identifier: MIT OR Apache-2.0

//! WASM32-specific implementation for local task execution
//!
//! This module provides a WASM32-compatible implementation that avoids using
//! std::sync::Condvar and std::sync::Mutex, which fail on the main thread due
//! to the atomics.wait restriction in WebAssembly.
//!
//! Currently contains stubs that will be implemented later.

use crate::observer::ObserverNotified;
use std::convert::Infallible;
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
#[cfg(test)]
pub use wasm_lite_std as thread;

/// WASM-specific newtype that wraps SpawnedStaticTask to implement Future
struct WasmStaticTaskFuture<F, N, E>
where
    F: Future + 'static,
    N: ObserverNotified<F::Output>,
    E: crate::SomeStaticExecutor,
    F::Output: 'static + Unpin,
{
    spawned: Pin<Box<crate::task::SpawnedStaticTask<F, N, E>>>,
}

impl<F, N, E> WasmStaticTaskFuture<F, N, E>
where
    F: Future + 'static,
    N: ObserverNotified<F::Output>,
    E: crate::SomeStaticExecutor,
    F::Output: 'static + Unpin,
{
    fn new(spawned: crate::task::SpawnedStaticTask<F, N, E>) -> Self {
        Self {
            spawned: Box::pin(spawned),
        }
    }
}

impl<F, N, E> Future for WasmStaticTaskFuture<F, N, E>
where
    F: Future + 'static,
    N: ObserverNotified<F::Output>,
    E: crate::SomeStaticExecutor,
    F::Output: 'static + Unpin,
{
    type Output = ();

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        // wasm_lite::console::log("WasmStaticTask::poll");

        // Delegate to the SpawnedStaticTask's poll method
        // Following the same pattern as in stdlib implementation

        // wasm_lite::console::log("WasmStaticTask::poll done");
        self.spawned.as_mut().poll::<Infallible>(cx, None, None)
    }
}

impl<F, N, E> Drop for WasmStaticTaskFuture<F, N, E>
where
    F: Future + 'static,
    N: ObserverNotified<F::Output>,
    E: crate::SomeStaticExecutor,
    F::Output: 'static + Unpin,
{
    fn drop(&mut self) {
        // Pairs with the `task_begin` in `run_static_task`.
        wasm_lite_std::task_finished();
    }
}

/// Helper to run a SpawnedLocalTask to completion using WASM32-compatible mechanisms
#[allow(dead_code)]
pub(crate) fn run_local_task<F, N, E>(_spawned: crate::task::SpawnedLocalTask<F, N, E>)
where
    F: Future,
    N: ObserverNotified<F::Output>,
    E: for<'a> crate::SomeLocalExecutor<'a>,
{
    panic!(
        "Local task spawning without a proper executor is no longer supported. Please configure a local executor before spawning local tasks."
    );
}

/// Waits asynchronously until the given deadline, using the JS `setTimeout` mechanism.
///
/// Returns immediately if the deadline has already passed. Unlike a blocking sleep,
/// this is safe to use on the main browser thread.
pub(crate) async fn wait_until(deadline: crate::sys::Instant) {
    let now = crate::sys::Instant::now();
    if deadline <= now {
        return;
    }
    wasm_lite_std::sleep_async(deadline.duration_since(now)).await;
}

/// Helper to run a SpawnedStaticTask to completion using WASM32-compatible mechanisms
pub(crate) fn run_static_task<F, N, E>(spawned: crate::task::SpawnedStaticTask<F, N, E>)
where
    F: Future + 'static,
    N: ObserverNotified<F::Output>,
    E: crate::SomeStaticExecutor,
    F::Output: 'static + Unpin,
{
    // Respect poll_after: conforming executors must not poll before this time
    // (common_poll asserts it).
    let poll_after = spawned.poll_after();

    // Wrap the SpawnedStaticTask in our WASM-specific future wrapper
    let wasm_future = WasmStaticTaskFuture::new(spawned);

    // Tell the runtime this thread has outstanding work, so a worker whose
    // entry point has returned is not torn down while this task is still
    // pending. `WasmStaticTaskFuture::drop` calls `task_finished`.
    wasm_lite_std::task_begin();
    wasm_lite_std::spawn_local(async move {
        wait_until(poll_after).await;
        wasm_future.await;
    });
}