use std::{fmt::Debug, marker::PhantomData};
use crate::{
AsStoreMut, AsStoreRef, LocalRwLock, LocalRwLockReadGuard, LocalRwLockWriteGuard, Store,
StoreContext, StoreInner, StoreMut, StorePtrWrapper, StoreRef,
};
use wasmer_types::StoreId;
pub struct StoreAsync {
pub(crate) id: StoreId,
pub(crate) inner: LocalRwLock<Box<StoreInner>>,
}
impl StoreAsync {
pub(crate) fn from_context(id: StoreId) -> Option<Self> {
match unsafe { StoreContext::try_get_current_async(id) } {
crate::GetStoreAsyncGuardResult::Ok(guard) => Some(Self {
id,
inner: crate::LocalRwLockWriteGuard::lock_handle(unsafe {
guard.guard.as_ref().unwrap()
}),
}),
_ => None,
}
}
pub fn into_store(self) -> Result<Store, Self> {
match self.inner.consume() {
Ok(unwrapped) => Ok(Store { inner: unwrapped }),
Err(lock) => Err(Self {
id: self.id,
inner: lock,
}),
}
}
pub fn read(&self) -> StoreAsyncReadLock {
if !StoreContext::is_empty() {
panic!("This method cannot be called from inside imported functions");
}
let store_ref = self
.inner
.try_read()
.expect("StoreAsync is locked for write");
StoreAsyncReadLock { inner: store_ref }
}
pub fn write(self) -> StoreAsyncWriteLock {
if !StoreContext::is_empty() {
panic!("This method cannot be called from inside imported functions");
}
let store_guard = self.inner.try_write().expect("StoreAsync is locked");
StoreAsyncWriteLock { inner: store_guard }
}
}
impl Debug for StoreAsync {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("StoreAsync").field("id", &self.id).finish()
}
}
pub trait AsStoreAsync {
fn store_ref(&self) -> &StoreAsync;
fn store(&self) -> StoreAsync {
let store = self.store_ref();
StoreAsync {
id: store.id,
inner: store.inner.clone(),
}
}
fn store_id(&self) -> StoreId {
self.store().id
}
fn read_lock(&self) -> impl Future<Output = StoreAsyncReadLock> {
StoreAsyncReadLock::acquire(self.store_ref())
}
fn write_lock(&self) -> impl Future<Output = StoreAsyncWriteLock> {
StoreAsyncWriteLock::acquire(self.store_ref())
}
}
impl AsStoreAsync for StoreAsync {
fn store_ref(&self) -> &StoreAsync {
self
}
}
pub struct StoreAsyncReadLock {
pub(crate) inner: LocalRwLockReadGuard<Box<StoreInner>>,
}
impl StoreAsyncReadLock {
pub(crate) async fn acquire(store: &StoreAsync) -> Self {
let store_ref = store.inner.read().await;
Self { inner: store_ref }
}
}
impl AsStoreRef for StoreAsyncReadLock {
fn as_store_ref(&self) -> StoreRef<'_> {
StoreRef { inner: &self.inner }
}
}
pub struct StoreAsyncWriteLock {
pub(crate) inner: LocalRwLockWriteGuard<Box<StoreInner>>,
}
impl StoreAsyncWriteLock {
pub(crate) async fn acquire(store: &StoreAsync) -> Self {
let store_guard = store.inner.write().await;
Self { inner: store_guard }
}
}
impl AsStoreRef for StoreAsyncWriteLock {
fn as_store_ref(&self) -> StoreRef<'_> {
StoreRef { inner: &self.inner }
}
}
impl AsStoreMut for StoreAsyncWriteLock {
fn as_store_mut(&mut self) -> StoreMut<'_> {
StoreMut {
inner: &mut self.inner,
}
}
fn objects_mut(&mut self) -> &mut super::StoreObjects {
&mut self.inner.objects
}
}