use std::collections::HashMap; use std::sync::{Arc, Mutex}; use crate::transfer::Transfer; use crate::Well; use uuid::Uuid; #[derive(Debug)] pub struct TransferRegionCache { interior: Arc>, } impl Default for TransferRegionCache { fn default() -> Self { Self::new() } } impl TransferRegionCache { pub fn new() -> Self { TransferRegionCache { interior: Arc::new(Mutex::new(TransferRegionCacheInterior::new())) } } pub fn add_overwrite(&self, tr: &Transfer) { let source = tr.transfer_region.get_source_wells(); let destination = tr.transfer_region.get_destination_wells(); let uuid = tr.id; if let Ok(mut interior) = self.interior.lock() { interior.cache.insert(uuid, InteriorWellSlices { source: source.into(), destination: destination.into(), }); } } pub fn generate_cache(&self, trs: &[Transfer]) { for tr in trs.iter() { self.add_overwrite(tr); } } pub fn invalidate(&self, tr: &Transfer) { if let Ok(mut interior) = self.interior.lock() { interior.cache.remove(&tr.id); } } pub fn get_source(&self, tr: &Transfer) -> Option> { self.get(tr, true) } pub fn get_or_calculate_source(&self, tr: &Transfer) -> Option> { if !self.has(tr) { self.add_overwrite(tr); } self.get_source(tr) } pub fn get_destination(&self, tr: &Transfer) -> Option> { self.get(tr, false) } pub fn get_or_calculate_destination(&self, tr: &Transfer) -> Option> { if !self.has(tr) { self.add_overwrite(tr); } self.get_destination(tr) } fn get(&self, tr: &Transfer, is_source: bool) -> Option> { if let Ok(interior) = self.interior.lock() { interior.cache.get(&tr.id).map(|x| if is_source { x.source.clone() } else { x.destination.clone() }) } else { None } } fn has(&self, tr: &Transfer) -> bool { if let Ok(interior) = self.interior.lock() { interior.cache.contains_key(&tr.get_uuid()) } else { false } } } impl Clone for TransferRegionCache { fn clone(&self) -> Self { // Clone the interior RC without letting anyone know // shhhh! TransferRegionCache { interior: self.interior.clone(), } } } #[derive(Debug)] struct TransferRegionCacheInterior { cache: HashMap, } impl TransferRegionCacheInterior { fn new() -> Self { TransferRegionCacheInterior { cache: HashMap::new() } } } #[derive(Debug)] struct InteriorWellSlices { source: Arc<[Well]>, destination: Arc<[Well]>, }