forked from ROMEO/obsw
141 lines
3.8 KiB
Rust
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(())
|
|
}
|
|
}
|