use crate::{
array::{
iterator::{
private::{InnerIter, Sealed},
IterLockFuture,
},
local_lock_atomic::handle::{LocalLockLocalChunksHandle, LocalLockLocalChunksMutHandle},
LocalLockLocalData,
},
darc::local_rw_darc::{LocalRwDarcReadGuard, LocalRwDarcWriteGuard},
Dist, IndexedLocalIterator, LamellarArray, LocalIterator, LocalLockArray,
};
use std::{
ops::{Deref, DerefMut},
sync::Arc,
};
#[derive(Clone)]
pub struct LocalLockLocalChunks<T: Dist> {
pub(crate) chunk_size: usize,
pub(crate) index: usize, pub(crate) end_index: usize, pub(crate) array: LocalLockArray<T>,
pub(crate) lock_guard: Arc<LocalRwDarcReadGuard<()>>,
}
impl<T: Dist> InnerIter for LocalLockLocalChunks<T> {
fn lock_if_needed(&self, _s: Sealed) -> Option<IterLockFuture> {
None
}
fn iter_clone(&self, _s: Sealed) -> Self {
LocalLockLocalChunks {
chunk_size: self.chunk_size,
index: self.index,
end_index: self.end_index,
array: self.array.clone(),
lock_guard: self.lock_guard.clone(),
}
}
}
pub struct LocalLockLocalChunksMut<T: Dist> {
pub(crate) chunk_size: usize,
pub(crate) index: usize, pub(crate) end_index: usize, pub(crate) array: LocalLockArray<T>,
pub(crate) lock_guard: Arc<LocalRwDarcWriteGuard<()>>,
}
impl<T: Dist> InnerIter for LocalLockLocalChunksMut<T> {
fn lock_if_needed(&self, _s: Sealed) -> Option<IterLockFuture> {
None
}
fn iter_clone(&self, _s: Sealed) -> Self {
LocalLockLocalChunksMut {
chunk_size: self.chunk_size,
index: self.index,
end_index: self.end_index,
array: self.array.clone(),
lock_guard: self.lock_guard.clone(),
}
}
}
#[derive(Debug)]
pub struct LocalLockMutChunkLocalData<'a, T: Dist> {
data: &'a mut [T],
_index: usize,
_lock_guard: Arc<LocalRwDarcWriteGuard<()>>,
}
impl<T: Dist> Deref for LocalLockMutChunkLocalData<'_, T> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.data
}
}
impl<T: Dist> DerefMut for LocalLockMutChunkLocalData<'_, T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.data
}
}
impl<T: Dist> LocalIterator for LocalLockLocalChunks<T> {
type Item = LocalLockLocalData<T>;
type Array = LocalLockArray<T>;
fn init(&self, start_i: usize, cnt: usize, _s: Sealed) -> Self {
let end_i = std::cmp::min(
(start_i + cnt) * self.chunk_size,
self.array.num_elems_local(),
);
let new_start_i = start_i * self.chunk_size;
LocalLockLocalChunks {
chunk_size: self.chunk_size,
index: new_start_i,
end_index: end_i,
array: self.array.clone(),
lock_guard: self.lock_guard.clone(),
}
}
fn array(&self) -> Self::Array {
self.array.clone()
}
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.end_index {
let start_i = self.index;
self.index += self.chunk_size;
let end_i = std::cmp::min(self.index, self.end_index);
Some(LocalLockLocalData {
array: self.array.clone(),
start_index: start_i,
end_index: end_i,
lock_guard: self.lock_guard.clone(),
})
} else {
None
}
}
fn elems(&self, in_elems: usize) -> usize {
in_elems / self.chunk_size + (in_elems % self.chunk_size != 0) as usize
}
fn advance_index(&mut self, count: usize) {
self.index = std::cmp::min(self.index + count * self.chunk_size, self.end_index);
}
}
impl<T: Dist> IndexedLocalIterator for LocalLockLocalChunks<T> {
fn iterator_index(&self, index: usize) -> Option<usize> {
if index * self.chunk_size < self.array.len() {
Some(index) } else {
None
}
}
}
impl<T: Dist + 'static> LocalIterator for LocalLockLocalChunksMut<T> {
type Item = LocalLockMutChunkLocalData<'static, T>;
type Array = LocalLockArray<T>;
fn init(&self, start_i: usize, cnt: usize, _s: Sealed) -> Self {
let end_i = std::cmp::min(
(start_i + cnt) * self.chunk_size,
self.array.num_elems_local(),
);
let new_start_i = start_i * self.chunk_size;
LocalLockLocalChunksMut {
chunk_size: self.chunk_size,
index: new_start_i,
end_index: end_i,
array: self.array.clone(),
lock_guard: self.lock_guard.clone(),
}
}
fn array(&self) -> Self::Array {
self.array.clone()
}
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.end_index {
let start_i = self.index;
self.index += self.chunk_size;
let end_i = std::cmp::min(self.index, self.end_index);
Some(LocalLockMutChunkLocalData {
data: unsafe {
std::slice::from_raw_parts_mut(
self.array.array.local_as_mut_ptr().offset(start_i as isize),
end_i - start_i,
)
},
_index: 0,
_lock_guard: self.lock_guard.clone(),
})
} else {
None
}
}
fn elems(&self, in_elems: usize) -> usize {
in_elems / self.chunk_size + (in_elems % self.chunk_size != 0) as usize
}
fn advance_index(&mut self, count: usize) {
self.index = std::cmp::min(self.index + count * self.chunk_size, self.end_index);
}
}
impl<T: Dist + 'static> IndexedLocalIterator for LocalLockLocalChunksMut<T> {
fn iterator_index(&self, index: usize) -> Option<usize> {
if index * self.chunk_size < self.array.len() {
Some(index) } else {
None
}
}
}
impl<T: Dist> LocalLockArray<T> {
pub fn read_local_chunks(&self, chunk_size: usize) -> LocalLockLocalChunksHandle<T> {
let lock = self.lock.read();
LocalLockLocalChunksHandle {
chunk_size,
index: 0,
end_index: 0,
array: self.clone(),
lock_handle: lock,
}
}
pub fn write_local_chunks(&self, chunk_size: usize) -> LocalLockLocalChunksMutHandle<T> {
let lock = self.lock.write();
LocalLockLocalChunksMutHandle {
chunk_size,
index: 0,
end_index: 0,
array: self.clone(),
lock_handle: lock,
}
}
}