diff --git a/.gitignore b/.gitignore index 1a91d0b..313c840 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ **/target Cargo.lock wasm3-sys/wrapper.h +.vscode diff --git a/src/function.rs b/src/function.rs index c5534a3..df1d20d 100644 --- a/src/function.rs +++ b/src/function.rs @@ -60,27 +60,27 @@ pub(crate) type NNM3Function = NonNull; /// A callable wasm3 function. /// This has a generic `call` function for up to 26 parameters emulating an overloading behaviour without having to resort to tuples. /// These are hidden to not pollute the documentation. -#[derive(Debug, Copy, Clone)] -pub struct Function<'rt, Args, Ret> { +#[derive(Debug, Clone)] +pub struct Function { raw: NNM3Function, - rt: &'rt Runtime, + rt: Runtime, _pd: PhantomData<*const (Args, Ret)>, } -impl<'rt, Args, Ret> Eq for Function<'rt, Args, Ret> {} -impl<'rt, Args, Ret> PartialEq for Function<'rt, Args, Ret> { +impl Eq for Function {} +impl PartialEq for Function { fn eq(&self, other: &Self) -> bool { self.raw == other.raw } } -impl<'rt, Args, Ret> Hash for Function<'rt, Args, Ret> { +impl Hash for Function { fn hash(&self, state: &mut H) { self.raw.hash(state); } } -impl<'rt, Args, Ret> Function<'rt, Args, Ret> +impl Function where Args: WasmArgs, Ret: WasmType, @@ -91,17 +91,17 @@ where } /// The module containing this function. - pub fn module(&self) -> Option> { + pub fn module(&self) -> Option { let module = unsafe { ffi::m3_GetFunctionModule(self.raw.as_ptr()) }; if !module.is_null() { - Some(Module::from_raw(self.rt, module)) + Some(Module::from_raw(&self.rt, module)) } else { None } } } -impl<'rt, Args, Ret> Function<'rt, Args, Ret> +impl Function where Args: WasmArgs, Ret: WasmType, @@ -125,13 +125,13 @@ where } #[inline] - pub(crate) fn from_raw(rt: &'rt Runtime, raw: NNM3Function) -> Result { + pub(crate) fn from_raw(rt: &Runtime, raw: NNM3Function) -> Result { if !Self::validate_sig(raw) { return Err(Error::InvalidFunctionSignature); } Ok(Function { raw, - rt, + rt: rt.clone(), _pd: PhantomData, }) } @@ -156,7 +156,7 @@ macro_rules! func_call_impl { (@do_impl) => {}; (@do_impl $($types:ident,)*) => { #[doc(hidden)] // this really pollutes the documentation - impl<'rt, $($types,)* Ret> Function<'rt, ($($types,)*), Ret> + impl<$($types,)* Ret> Function<($($types,)*), Ret> where Ret: WasmType, ($($types,)*): WasmArgs, @@ -173,7 +173,7 @@ macro_rules! func_call_impl { } func_call_impl!(A, B, C, D, E, F, G, H, J, K, L, M, N, O, P, Q); -impl<'rt, ARG, Ret> Function<'rt, ARG, Ret> +impl Function where Ret: WasmType, ARG: WasmArg, @@ -188,7 +188,7 @@ where } } -impl<'rt, Ret> Function<'rt, (), Ret> +impl Function<(), Ret> where Ret: WasmType, { diff --git a/src/module.rs b/src/module.rs index 43f36b9..48a8ce5 100644 --- a/src/module.rs +++ b/src/module.rs @@ -67,12 +67,12 @@ impl ParsedModule { /// A loaded module belonging to a specific runtime. Allows for linking and looking up functions. // needs no drop as loaded modules will be cleaned up by the runtime -pub struct Module<'rt> { +pub struct Module { raw: ffi::IM3Module, - rt: &'rt Runtime, + rt: Runtime, } -impl<'rt> Module<'rt> { +impl Module { /// Parses a wasm module from raw bytes. #[inline] pub fn parse>>( @@ -204,7 +204,7 @@ impl<'rt> Module<'rt> { /// * a memory allocation failed /// * no function by the given name in the given module could be found /// * the function has been found but the signature did not match - pub fn find_function(&self, function_name: &str) -> Result> + pub fn find_function(&self, function_name: &str) -> Result> where Args: crate::WasmArgs, Ret: crate::WasmType, @@ -228,9 +228,9 @@ impl<'rt> Module<'rt> { } } -impl<'rt> Module<'rt> { - pub(crate) fn from_raw(rt: &'rt Runtime, raw: ffi::IM3Module) -> Self { - Module { raw, rt } +impl Module { + pub(crate) fn from_raw(rt: &Runtime, raw: ffi::IM3Module) -> Self { + Module { raw, rt: rt.clone() } } } diff --git a/src/runtime.rs b/src/runtime.rs index 2617a9f..fb176d2 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -1,4 +1,5 @@ use alloc::boxed::Box; +use alloc::rc::Rc; use alloc::vec::Vec; use core::cell::UnsafeCell; use core::pin::Pin; @@ -13,8 +14,14 @@ use crate::utils::str_to_cstr_owned; type PinnedAnyClosure = Pin>; /// A runtime context for wasm3 modules. -#[derive(Debug)] +#[derive(Clone, Debug)] pub struct Runtime { + inner: Rc, +} + +/// A runtime context for wasm3 modules. +#[derive(Debug)] +struct RuntimeInner { raw: NonNull, environment: Environment, // holds all linked closures so that they properly get disposed of when runtime drops @@ -38,17 +45,18 @@ impl Runtime { )) } .ok_or_else(Error::malloc_error) - .map(|raw| Runtime { + .map(|raw| RuntimeInner { raw, environment: environment.clone(), closure_store: UnsafeCell::new(Vec::new()), module_data: UnsafeCell::new(Vec::new()), }) + .map(|inner| Runtime { inner: Rc::new(inner) }) } /// Parses and loads a module from bytes. pub fn parse_and_load_module>>(&self, bytes: TData) -> Result { - Module::parse(&self.environment, bytes).and_then(|module| self.load_module(module)) + Module::parse(&self.inner.environment, bytes).and_then(|module| self.load_module(module)) } /// Loads a parsed module returning the module if unsuccessful. @@ -57,14 +65,14 @@ impl Runtime { /// /// This function will error if the module's environment differs from the one this runtime uses. pub fn load_module(&self, module: ParsedModule) -> Result { - if &self.environment != module.environment() { + if &self.inner.environment != module.environment() { Err(Error::ModuleLoadEnvMismatch) } else { let raw_mod = module.as_ptr(); - Error::from_ffi_res(unsafe { ffi::m3_LoadModule(self.raw.as_ptr(), raw_mod) })?; + Error::from_ffi_res(unsafe { ffi::m3_LoadModule(self.inner.raw.as_ptr(), raw_mod) })?; // SAFETY: Runtime isn't Send, therefor this access is single-threaded and kept alive only for the Vec::push call // as such this can not alias. - unsafe { (*self.module_data.get()).push(module.take_data()) }; + unsafe { (*self.inner.module_data.get()).push(module.take_data()) }; Ok(Module::from_raw(self, raw_mod)) } @@ -118,15 +126,15 @@ impl Runtime { impl Runtime { pub(crate) fn push_closure(&self, closure: PinnedAnyClosure) { - unsafe { (*self.closure_store.get()).push(closure) }; + unsafe { (*self.inner.closure_store.get()).push(closure) }; } pub(crate) fn as_ptr(&self) -> ffi::IM3Runtime { - self.raw.as_ptr() + self.inner.raw.as_ptr() } } -impl Drop for Runtime { +impl Drop for RuntimeInner { fn drop(&mut self) { unsafe { ffi::m3_FreeRuntime(self.raw.as_ptr()) }; }