Skip to main content

wasmer/wasm_c_api/
store.rs

1use super::engine::wasm_engine_t;
2use std::cell::UnsafeCell;
3use std::rc::{Rc, Weak};
4use wasmer_api::{AsStoreMut, AsStoreRef, Store, StoreMut, StoreRef as BaseStoreRef};
5
6#[derive(Clone)]
7pub struct StoreRef {
8    inner: Rc<UnsafeCell<Store>>,
9}
10
11impl StoreRef {
12    pub unsafe fn store(&self) -> BaseStoreRef<'_> {
13        unsafe { (*self.inner.get()).as_store_ref() }
14    }
15
16    pub unsafe fn store_mut(&mut self) -> StoreMut<'_> {
17        unsafe { (*self.inner.get()).as_store_mut() }
18    }
19
20    /// Create a non-owning handle to this store.
21    ///
22    /// Host-function callbacks must not capture a strong [`StoreRef`]: the
23    /// function lives inside the store's arena, so a strong clone would form a
24    /// store → function → store cycle and leak the whole store. Callbacks
25    /// capture a [`WeakStoreRef`] instead and upgrade it per call.
26    pub fn downgrade(&self) -> WeakStoreRef {
27        WeakStoreRef {
28            inner: Rc::downgrade(&self.inner),
29        }
30    }
31}
32
33/// A non-owning handle to a store, held by host-function callbacks.
34#[derive(Clone)]
35pub struct WeakStoreRef {
36    inner: Weak<UnsafeCell<Store>>,
37}
38
39// SAFETY: wasm-c-api stores are single-threaded (a documented invariant of the
40// C API). Host callbacks are `Send + Sync`-bound by `Function::new_with_env`,
41// so this handle must be too; it is never actually shared across threads.
42unsafe impl Send for WeakStoreRef {}
43unsafe impl Sync for WeakStoreRef {}
44
45impl WeakStoreRef {
46    /// Upgrade to a strong [`StoreRef`], or `None` if the store has been
47    /// dropped (which cannot happen while one of its callbacks is running).
48    pub fn upgrade(&self) -> Option<StoreRef> {
49        self.inner.upgrade().map(|inner| StoreRef { inner })
50    }
51}
52
53/// Opaque type representing a WebAssembly store.
54#[allow(non_camel_case_types)]
55pub struct wasm_store_t {
56    pub(crate) inner: StoreRef,
57}
58
59/// Creates a new WebAssembly store given a specific [engine][super::engine].
60///
61/// # Example
62///
63/// See the module's documentation.
64#[unsafe(no_mangle)]
65pub unsafe extern "C" fn wasm_store_new(
66    engine: Option<&wasm_engine_t>,
67) -> Option<Box<wasm_store_t>> {
68    let engine = engine?;
69    let store = Store::new(engine.inner.clone());
70
71    Some(Box::new(wasm_store_t {
72        inner: StoreRef {
73            inner: Rc::new(UnsafeCell::new(store)),
74        },
75    }))
76}
77
78/// Deletes a WebAssembly store.
79///
80/// # Example
81///
82/// See the module's documentation.
83#[unsafe(no_mangle)]
84pub unsafe extern "C" fn wasm_store_delete(_store: Option<Box<wasm_store_t>>) {}