use crate::core::storage::{Allocator, Scalar, StorageBackend};
#[derive(Debug, Clone, Copy)]
pub struct ScratchSpec {
pub slabs: usize,
pub slab_len: usize,
}
impl ScratchSpec {
pub const NONE: Self = Self {
slabs: 0,
slab_len: 0,
};
}
pub struct Scratch<T: Scalar, S: StorageBackend<T>> {
slabs: Vec<S>,
_marker: std::marker::PhantomData<fn() -> T>,
}
impl<T: Scalar, S: StorageBackend<T>> Scratch<T, S> {
pub fn allocate<A: Allocator<T, Storage = S>>(spec: ScratchSpec, alloc: &A) -> Self {
Self {
slabs: (0..spec.slabs)
.map(|_| alloc.allocate(spec.slab_len))
.collect(),
_marker: std::marker::PhantomData,
}
}
#[inline(always)]
pub fn slab_mut(&mut self, i: usize) -> &mut [T] {
self.slabs[i].as_mut_slice()
}
pub fn slabs_mut(&mut self) -> impl Iterator<Item = &mut [T]> {
self.slabs
.iter_mut()
.map(super::storage::StorageBackend::as_mut_slice)
}
}
pub struct ScratchPool<T: Scalar, S: StorageBackend<T>> {
slots: Vec<parking_lot::Mutex<Scratch<T, S>>>,
}
impl<T: Scalar, S: StorageBackend<T>> ScratchPool<T, S> {
pub fn allocate<A: Allocator<T, Storage = S>>(
spec: ScratchSpec,
alloc: &A,
concurrency: usize,
) -> Self {
Self {
slots: (0..concurrency.max(1))
.map(|_| parking_lot::Mutex::new(Scratch::allocate(spec, alloc)))
.collect(),
}
}
pub fn checkout(&self) -> parking_lot::MutexGuard<'_, Scratch<T, S>> {
for slot in &self.slots {
if let Some(guard) = slot.try_lock() {
return guard;
}
}
self.slots[0].lock()
}
}