use parking_lot::Mutex; use shared::core::geometry::{Bounds2i, Point2i}; use shared::utils::containers::DeviceArray2D; use std::collections::HashSet; use std::hash::Hash; use std::ops::{Deref, DerefMut}; use std::sync::Arc; pub struct InternCache { cache: Mutex>>, } impl InternCache where T: Eq + Clone + Hash, { pub fn new() -> Self { Self { cache: Mutex::new(HashSet::new()), } } pub fn lookup(&self, value: T) -> Arc { let mut lock = self.cache.lock(); if let Some(existing) = lock.get(&value) { return existing.clone(); } let new_item = Arc::new(value); lock.insert(Arc::clone(&new_item)); new_item } } #[derive(Debug, Clone)] pub struct Array2D { pub device: DeviceArray2D, values: Vec, } impl Deref for Array2D { type Target = DeviceArray2D; fn deref(&self) -> &Self::Target { &self.device } } impl DerefMut for Array2D { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.device } } impl Array2D { pub fn as_slice(&self) -> &[T] { &self.values } fn from_vec(extent: Bounds2i, mut values: Vec) -> Self { let width = extent.p_max.x() - extent.p_min.x(); let device = DeviceArray2D { extent, values: values.as_mut_ptr().into(), stride: width, }; Self { device, values } } } impl Array2D { pub fn new(extent: Bounds2i) -> Self { let n = extent.area() as usize; let storage = vec![T::default(); n]; Self::from_vec(extent, storage) } pub fn new_dims(nx: i32, ny: i32) -> Self { let extent = Bounds2i::from_points(Point2i::new(0, 0), Point2i::new(nx, ny)); Self::new(extent) } pub fn new_filled(nx: i32, ny: i32, val: T) -> Self { let extent = Bounds2i::from_points(Point2i::new(0, 0), Point2i::new(nx, ny)); let n = (nx * ny) as usize; let storage = vec![val; n]; Self::from_vec(extent, storage) } }