use std::sync::Arc;
use anyhow::Result;
use log::trace;
use tokio::task::JoinHandle;
use wasmtime::{ResourceLimiter, Val};
use crate::env::Environment;
use crate::runtimes::wasmtime::{WasmtimeCompiledModule, WasmtimeRuntime};
use crate::state::ProcessState;
use crate::{Process, Signal, WasmProcess};
pub async fn spawn_wasm<S>(
env: Arc<dyn Environment>,
runtime: WasmtimeRuntime,
module: &WasmtimeCompiledModule<S>,
state: S,
function: &str,
params: Vec<Val>,
link: Option<(Option<i64>, Arc<dyn Process>)>,
) -> Result<(JoinHandle<Result<S>>, Arc<dyn Process>)>
where
S: ProcessState + Send + Sync + ResourceLimiter + 'static,
{
let id = state.id();
trace!("Spawning process: {}", id);
let signal_mailbox = state.signal_mailbox().clone();
let message_mailbox = state.message_mailbox().clone();
let instance = runtime.instantiate(module, state).await?;
let function = function.to_string();
let fut = async move { instance.call(&function, params).await };
let child_process = crate::new(fut, id, env.clone(), signal_mailbox.1, message_mailbox);
let child_process_handle = Arc::new(WasmProcess::new(id, signal_mailbox.0.clone()));
env.add_process(id, child_process_handle.clone());
if let Some((tag, process)) = link {
process.send(Signal::Link(None, child_process_handle.clone()));
tokio::task::yield_now().await;
signal_mailbox
.0
.send(Signal::Link(tag, process))
.expect("receiver must exist at this point");
}
trace!("Process size: {}", std::mem::size_of_val(&child_process));
let join = tokio::task::spawn(child_process);
Ok((join, child_process_handle))
}