use crate::check_global_threading_available; use super::objectmanager::SystemObjectIF; use super::{mutex, objectmanager}; #[derive(Copy, Clone, PartialEq)] pub struct TypeId { id: usize, } // inspired by Jack Wrenn at https://github.com/jswrenn/deflect/ pub trait HasTypeId { #[inline(never)] fn get_type_id(&self) -> TypeId { TypeId { id: Self::get_type_id as usize, } } } pub trait DatapoolOwnerIF { fn get_set(&self, _type_id: TypeId) -> Option<&dyn DataSetIF> { None } } pub trait DataSetIF { fn get_type_id(&self) -> TypeId; fn get_actual_data(&self) -> &dyn HasTypeId; fn get_mutex(&self) -> mutex::RawMutex; } pub struct OwnedDataset { actual_data: T, mutex: mutex::RawMutex, } pub struct ReferencedDataset { //we use a pointer here to avoid lifetimes actual_data: Option<*const T>, mutex: Option, } impl DataSetIF for OwnedDataset { fn get_type_id(&self) -> TypeId { self.actual_data.get_type_id() } fn get_actual_data(&self) -> &dyn HasTypeId { // only return pointer when threading check_global_threading_available!(); &self.actual_data } fn get_mutex(&self) -> mutex::RawMutex { return self.mutex.clone(); } } impl OwnedDataset { pub fn new() -> OwnedDataset { OwnedDataset:: { actual_data: T::default(), mutex: mutex::RawMutex::new(), } } pub fn new_default(default_values: T) -> OwnedDataset { OwnedDataset:: { actual_data: default_values, mutex: mutex::RawMutex::new(), } } pub fn read(&mut self) -> Result { let _mutex_guard = match self.mutex.take() { Err(()) => return Err(()), Ok(guard) => guard, }; Ok(self.actual_data.clone()) } //TODO do we want to know if it fails? pub fn commit(&mut self, data: T) { let _mutex_guard = match self.mutex.take() { Err(()) => return, Ok(guard) => guard, }; self.actual_data = data; } fn initialize(&mut self) {} } impl ReferencedDataset { pub fn new() -> ReferencedDataset { ReferencedDataset:: { actual_data: None, mutex: None, } } pub fn read(&mut self) -> Result { let _mutex_guard = match &self.mutex { None => return Err(()), Some(mutex) => match mutex.take() { Err(()) => return Err(()), Ok(guard) => guard, }, }; let pointer = match self.actual_data { None => return Err(()), Some(data) => data, }; // we are only allowed to use the pointer during threading check_global_threading_available!(); Ok(unsafe { (*pointer).clone() }) } pub fn initialize( &mut self, object_manager: &dyn objectmanager::ObjectManager, owner_of_the_set: objectmanager::ObjectId, ) -> Result<(), ()> { let owner = object_manager.get_object(owner_of_the_set)?; let temp: T = T::default(); //TODO find nicer solution whithout local instance and trait bound to Default let type_id = temp.get_type_id(); let other_set = match owner.get_set(type_id) { None => { return Err(()); } Some(set) => set, }; //pointer cast is safe because we checked the type_id //getting pointer to avoid lifetime check self.actual_data = Some(other_set.get_actual_data() as *const dyn HasTypeId as *const T); self.mutex = Some(other_set.get_mutex()); Ok(()) } }