2024-02-01 17:10:42 +01:00

141 lines
3.8 KiB
Rust

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<T: HasTypeId + Clone> {
actual_data: T,
mutex: mutex::RawMutex,
}
pub struct ReferencedDataset<T: HasTypeId + Clone> {
//we use a pointer here to avoid lifetimes
actual_data: Option<*const T>,
mutex: Option<mutex::RawMutex>,
}
impl<T: HasTypeId + Clone + Default> DataSetIF for OwnedDataset<T> {
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<T: HasTypeId + Clone + Default> OwnedDataset<T> {
pub fn new() -> OwnedDataset<T> {
OwnedDataset::<T> {
actual_data: T::default(),
mutex: mutex::RawMutex::new(),
}
}
pub fn new_default(default_values: T) -> OwnedDataset<T> {
OwnedDataset::<T> {
actual_data: default_values,
mutex: mutex::RawMutex::new(),
}
}
pub fn read(&mut self) -> Result<T, ()> {
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<T: HasTypeId + Clone + Default> ReferencedDataset<T> {
pub fn new() -> ReferencedDataset<T> {
ReferencedDataset::<T> {
actual_data: None,
mutex: None,
}
}
pub fn read(&mut self) -> Result<T, ()> {
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(())
}
}