use std::sync::Arc;
use crate::{
AsStoreMut, Memory,
error::AtomicsError,
location::{MemoryLocation, SharedMemoryOps},
vm::VMMemory,
vm::VMSharedMemory,
};
pub struct SharedMemory {
memory: VMSharedMemory,
ops: Option<Arc<dyn SharedMemoryOps + Send + Sync>>,
}
impl std::fmt::Debug for SharedMemory {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SharedMemory").finish()
}
}
impl Clone for SharedMemory {
fn clone(&self) -> Self {
Self {
memory: self.memory.clone(),
ops: self.ops.clone(),
}
}
}
impl SharedMemory {
pub(crate) fn new(memory: VMSharedMemory) -> Self {
Self { memory, ops: None }
}
pub(crate) fn new_with_ops(
memory: VMSharedMemory,
ops: Arc<dyn SharedMemoryOps + Send + Sync>,
) -> Self {
Self {
memory,
ops: Some(ops),
}
}
pub fn attach(self, store: &mut impl AsStoreMut) -> Memory {
let memory = self.memory.into_vm_memory(store);
Memory::new_from_existing(store, memory)
}
#[inline]
fn ops(&self) -> Result<&(dyn SharedMemoryOps + Send + Sync), AtomicsError> {
self.ops
.as_ref()
.map(|ops| ops.as_ref())
.ok_or(AtomicsError::Unimplemented)
}
pub fn notify(&self, location: MemoryLocation, count: u32) -> Result<u32, AtomicsError> {
self.ops()?.notify(location, count)
}
pub fn wait(
&self,
location: MemoryLocation,
timeout: Option<std::time::Duration>,
) -> Result<u32, AtomicsError> {
self.ops()?.wait(location, timeout)
}
pub fn disable_atomics(&self) -> Result<(), AtomicsError> {
self.ops()?.disable_atomics()
}
pub fn wake_all_atomic_waiters(&self) -> Result<(), AtomicsError> {
self.ops()?.wake_all_atomic_waiters()
}
}
#[cfg(test)]
mod tests {
#[test]
pub fn ensure_shared_memory_is_send_and_sync() {
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
assert_send::<super::SharedMemory>();
assert_sync::<super::SharedMemory>();
}
}