cljrs_runtime/env/async_hook.rs
1//! Hook trait for the optional async runtime (`cljrs-async`).
2//!
3//! Core crates never import Tokio. When `cljrs-async` is linked, it calls
4//! `GlobalEnv::set_async_runtime` to install itself. The evaluator then
5//! delegates `^:async` fn dispatch through this trait.
6
7use cljrs_value::Value;
8
9use crate::env::env::Env;
10
11use crate::env::error::EvalResult;
12
13/// Interface implemented by `cljrs-async` and registered with `GlobalEnv`.
14///
15/// All methods are called from the LocalSet thread, so `Value` / `Env` need
16/// not be `Send`. The trait itself must be `Send + Sync` so the
17/// `Arc<dyn AsyncRuntime>` inside `GlobalEnv` can be shared.
18pub trait AsyncRuntime: Send + Sync {
19 /// Spawn a call to an `^:async` function as a LocalSet task.
20 ///
21 /// `callee` is the `Value::Fn` being invoked, `args` are the already-
22 /// evaluated arguments, `env` is the calling environment. Returns a
23 /// `Value::Future` immediately; the body runs concurrently.
24 fn spawn_async_call(&self, callee: Value, args: Vec<Value>, env: Env) -> Value;
25
26 /// Spawn an ordinary synchronous call on a parking-capable fiber.
27 /// Runtimes without fibers retain their async task implementation.
28 fn spawn_fiber_call(&self, callee: Value, args: Vec<Value>, env: Env) -> EvalResult {
29 Ok(self.spawn_async_call(callee, args, env))
30 }
31
32 /// `await` support: if `val` is one of this runtime's channels, take from it,
33 /// parking the calling fiber (or blocking the OS thread outside a fiber),
34 /// and keep it rooted for the whole wait. On wasm32, which cannot park, a
35 /// ready value (or `nil` for a closed channel) is returned at once and a take
36 /// that would block is an error. Returns `None` for any other value.
37 fn take_if_channel(&self, val: &Value) -> Option<EvalResult> {
38 let _ = val;
39 None
40 }
41
42 /// Block the current OS thread until a value can be taken from the channel.
43 ///
44 /// Used by the IR interpreter's sync-context fallback for `ChanTake`.
45 /// Returns `Value::Nil` on a closed channel.
46 fn chan_take_blocking(&self, chan: Value) -> EvalResult;
47
48 /// Block the current OS thread until the value is accepted by the channel.
49 ///
50 /// Used by the IR interpreter's sync-context fallback for `ChanPut`.
51 fn chan_put_blocking(&self, chan: Value, val: Value) -> EvalResult<()>;
52}