use std::{
cell::{Ref, RefCell, RefMut},
ops::Deref,
rc::Rc,
sync::{Arc, LockResult, RwLock, RwLockReadGuard, RwLockWriteGuard},
};
use crate::{Array, BorrowAtRuntime, BorrowAtRuntimeMut};
pub struct ArraySharedRef<ArrayImpl, const NDIM: usize>(Rc<RefCell<Array<ArrayImpl, NDIM>>>);
impl<ArrayImpl, const NDIM: usize> Clone for ArraySharedRef<ArrayImpl, NDIM> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<ArrayImpl, const NDIM: usize> ArraySharedRef<ArrayImpl, NDIM> {
pub fn new(arr: Array<ArrayImpl, NDIM>) -> Self {
ArraySharedRef(Rc::new(RefCell::new(arr)))
}
}
pub struct ArrayAtomicSharedRef<ArrayImpl, const NDIM: usize>(Arc<RwLock<Array<ArrayImpl, NDIM>>>);
impl<ArrayImpl, const NDIM: usize> Clone for ArrayAtomicSharedRef<ArrayImpl, NDIM> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<ArrayImpl, const NDIM: usize> ArrayAtomicSharedRef<ArrayImpl, NDIM> {
pub fn new(arr: Array<ArrayImpl, NDIM>) -> Self {
ArrayAtomicSharedRef(Arc::new(RwLock::new(arr)))
}
}
impl<ArrayImpl, const NDIM: usize> BorrowAtRuntime for ArraySharedRef<ArrayImpl, NDIM> {
type Target<'a>
= Ref<'a, Array<ArrayImpl, NDIM>>
where
Self: 'a;
fn borrow(&self) -> Self::Target<'_> {
RefCell::borrow(self.0.deref())
}
}
impl<ArrayImpl, const NDIM: usize> BorrowAtRuntimeMut for ArraySharedRef<ArrayImpl, NDIM> {
type Target<'a>
= RefMut<'a, Array<ArrayImpl, NDIM>>
where
Self: 'a;
fn borrow_mut(&self) -> Self::Target<'_> {
RefCell::borrow_mut(self.0.deref())
}
}
impl<ArrayImpl, const NDIM: usize> BorrowAtRuntime for ArrayAtomicSharedRef<ArrayImpl, NDIM> {
type Target<'a>
= LockResult<RwLockReadGuard<'a, Array<ArrayImpl, NDIM>>>
where
Self: 'a;
fn borrow(&self) -> Self::Target<'_> {
self.0.read()
}
}
impl<ArrayImpl, const NDIM: usize> BorrowAtRuntimeMut for ArrayAtomicSharedRef<ArrayImpl, NDIM> {
type Target<'a>
= LockResult<RwLockWriteGuard<'a, Array<ArrayImpl, NDIM>>>
where
Self: 'a;
fn borrow_mut(&self) -> Self::Target<'_> {
self.0.write()
}
}
impl<ArrayImpl, const NDIM: usize> Array<ArrayImpl, NDIM> {
pub fn into_shared(self) -> ArraySharedRef<ArrayImpl, NDIM> {
ArraySharedRef(Rc::new(RefCell::new(self)))
}
pub fn into_shared_atomic(self) -> ArrayAtomicSharedRef<ArrayImpl, NDIM> {
ArrayAtomicSharedRef(Arc::new(RwLock::new(self)))
}
}