use core::{cell::UnsafeCell, fmt::Debug};
use zeroize::Zeroizing;
use crate::{
memory::{FlexibleMemoryManager, MemoryManager, RefCount},
word::{CompositeWord, Shape, Word, WordIdx, Words, on_all_words},
};
pub trait WordPool: Sized + Debug + Default {
fn alloc<W: Word, const N: usize>(&mut self) -> WordIdx<W, N>;
fn increase_refcount<W: Word, const N: usize>(&mut self, idx: WordIdx<W, N>);
fn decrease_refcount<W: Word, const N: usize>(&mut self, idx: WordIdx<W, N>);
fn read<W: Word, const N: usize>(&self, idx: WordIdx<W, N>) -> CompositeWord<W, N>;
fn write<W: Word, const N: usize>(&mut self, idx: WordIdx<W, N>, word: CompositeWord<W, N>);
}
pub trait WordSource: Debug + Default {
fn words<W: Word>(&self) -> &[W];
fn words_mut<W: Word>(&mut self) -> &mut [W];
fn resize<W: Word>(&mut self, new_len: usize);
}
#[derive(Debug)]
pub struct WordSourceWrapper {
words: Zeroizing<Words>,
}
impl WordSourceWrapper {
pub fn new(words: Words) -> Self {
return Self {
words: Zeroizing::new(words),
};
}
}
impl WordSource for WordSourceWrapper {
fn words<W: Word>(&self) -> &[W] {
return self.words.as_vec::<W>();
}
fn words_mut<W: Word>(&mut self) -> &mut [W] {
return self.words.as_vec_mut::<W>();
}
fn resize<W: Word>(&mut self, new_len: usize) {
self.words.as_vec_mut::<W>().resize(new_len, W::ZERO);
}
}
impl Default for WordSourceWrapper {
fn default() -> Self {
return Self::new(Words::new());
}
}
#[derive(Debug)]
pub struct WordPoolWrapper<WS: WordSource, M: MemoryManager> {
word_source: WS,
memory_manager: M,
}
impl<WS: WordSource, M: MemoryManager> WordPoolWrapper<WS, M> {
pub fn new(word_source: WS, memory_manager: M) -> Self {
return Self {
word_source,
memory_manager,
};
}
}
impl<WS: WordSource, M: MemoryManager> WordPool for WordPoolWrapper<WS, M> {
fn alloc<W: Word, const N: usize>(&mut self) -> WordIdx<W, N> {
let (idx, vec_len) = self.memory_manager.alloc::<W, N>();
self.word_source.resize::<W>(vec_len);
return idx;
}
fn increase_refcount<W: Word, const N: usize>(&mut self, idx: WordIdx<W, N>) {
self.memory_manager.increase_refcount::<W, N>(idx);
}
fn decrease_refcount<W: Word, const N: usize>(&mut self, idx: WordIdx<W, N>) {
self.memory_manager.decrease_refcount::<W, N>(idx);
}
fn read<W: Word, const N: usize>(&self, idx: WordIdx<W, N>) -> CompositeWord<W, N> {
let words = self.word_source.words::<W>();
let res = CompositeWord::from_le_words(idx.into_array().map(|i| words[i]));
return res;
}
fn write<W: Word, const N: usize>(&mut self, idx: WordIdx<W, N>, word: CompositeWord<W, N>) {
let words = self.word_source.words_mut::<W>();
for (i, w) in idx.into_array().into_iter().zip(word.to_le_words()) {
words[i] = w;
}
}
}
impl<WS: WordSource, M: MemoryManager> Default for WordPoolWrapper<WS, M> {
fn default() -> Self {
return Self::new(WS::default(), M::new());
}
}
#[allow(type_alias_bounds)]
pub type OwnedFlexibleWordPool<RC: RefCount> =
WordPoolWrapper<WordSourceWrapper, FlexibleMemoryManager<RC>>;
struct GlobalWords(UnsafeCell<Words>);
unsafe impl Sync for GlobalWords {}
static GLOBAL_WORDS: GlobalWords = GlobalWords(UnsafeCell::new(Words::new()));
#[derive(Debug, Default)]
pub struct GlobalWordSource;
impl WordSource for GlobalWordSource {
fn words<W: Word>(&self) -> &[W] {
unsafe { (&*GLOBAL_WORDS.0.get()).as_vec::<W>() }
}
fn words_mut<W: Word>(&mut self) -> &mut [W] {
unsafe { (&mut *GLOBAL_WORDS.0.get()).as_vec_mut::<W>() }
}
fn resize<W: Word>(&mut self, new_len: usize) {
unsafe { (&mut *GLOBAL_WORDS.0.get()).as_vec_mut::<W>() }.resize(new_len, W::ZERO);
}
}
#[allow(type_alias_bounds)]
pub type GlobalFlexibleWordPool<RC: RefCount> =
WordPoolWrapper<GlobalWordSource, FlexibleMemoryManager<RC>>;
impl<RC: RefCount> GlobalFlexibleWordPool<RC> {
pub fn shape() -> Shape {
return unsafe { (&mut *GLOBAL_WORDS.0.get()).shape() };
}
pub fn capacity() -> Shape {
return unsafe { (&mut *GLOBAL_WORDS.0.get()).capacity() };
}
pub fn reserve(capacity: Shape) {
let current_capacity = Self::capacity();
let additional = capacity.zip(¤t_capacity, |desired, current| {
if desired < current {
0
} else {
desired - current
}
});
on_all_words!(W, {
let words = unsafe { (&mut *GLOBAL_WORDS.0.get()).as_vec_mut::<W>() };
words.reserve_exact(*additional.as_value::<W>());
});
}
pub fn resize(new_len: Shape) {
on_all_words!(W, {
let words = unsafe { (&mut *GLOBAL_WORDS.0.get()).as_vec_mut::<W>() };
words.resize(*new_len.as_value::<W>(), <W as Word>::ZERO);
});
assert_eq!(Self::shape(), new_len);
}
}