this time, we won't reinvent the wheel

This commit is contained in:
2024-02-03 00:03:49 +01:00
parent 3155243ae9
commit 4460e470b2
3 changed files with 26 additions and 41 deletions

View File

@ -1,52 +1,39 @@
use core::any::Any;
use crate::check_global_threading_available; use crate::check_global_threading_available;
use super::objectmanager::SystemObjectIF; use super::objectmanager::SystemObjectIF;
use super::{mutex, objectmanager}; 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 { pub trait DatapoolOwnerIF {
fn get_set(&self, _type_id: TypeId) -> Option<&dyn DataSetIF> { fn get_set(&self, _type_id: core::any::TypeId) -> Option<&dyn DataSetIF> {
None None
} }
} }
pub trait DataSetIF { pub trait DataSetIF {
fn get_type_id(&self) -> TypeId; fn get_type_id(&self) -> core::any::TypeId; // TODO can we get rid of this? Currently, it helps implementing DatapoolOwnerIF::get_set() but if we can optimize/generate that, this might be not needed any more
fn get_actual_data(&self) -> &dyn HasTypeId; fn get_actual_data(&self) -> &dyn core::any::Any;
fn get_mutex(&self) -> mutex::RawMutex; fn get_mutex(&self) -> mutex::RawMutex;
} }
pub struct OwnedDataset<T: HasTypeId + Clone> { pub struct OwnedDataset<T: Clone> {
actual_data: T, actual_data: T,
mutex: mutex::RawMutex, mutex: mutex::RawMutex,
} }
pub struct ReferencedDataset<T: HasTypeId + Clone> { pub struct ReferencedDataset<T: Clone> {
//we use a pointer here to avoid lifetimes //we use a pointer here to avoid lifetimes
actual_data: Option<*const T>, actual_data: Option<*const T>,
mutex: Option<mutex::RawMutex>, mutex: Option<mutex::RawMutex>,
} }
impl<T: HasTypeId + Clone + Default> DataSetIF for OwnedDataset<T> { impl<T: Clone + Default + 'static> DataSetIF for OwnedDataset<T> {
fn get_type_id(&self) -> TypeId { fn get_type_id(&self) -> core::any::TypeId {
self.actual_data.get_type_id() core::any::TypeId::of::<T>()
} }
fn get_actual_data(&self) -> &dyn HasTypeId { fn get_actual_data(&self) -> &dyn core::any::Any {
// only return pointer when threading // only return pointer when threading
check_global_threading_available!(); check_global_threading_available!();
&self.actual_data &self.actual_data
@ -57,7 +44,7 @@ impl<T: HasTypeId + Clone + Default> DataSetIF for OwnedDataset<T> {
} }
} }
impl<T: HasTypeId + Clone + Default> OwnedDataset<T> { impl<T: Clone + Default> OwnedDataset<T> {
pub fn new() -> OwnedDataset<T> { pub fn new() -> OwnedDataset<T> {
OwnedDataset::<T> { OwnedDataset::<T> {
actual_data: T::default(), actual_data: T::default(),
@ -90,7 +77,7 @@ impl<T: HasTypeId + Clone + Default> OwnedDataset<T> {
} }
} }
impl<T: HasTypeId + Clone + Default> ReferencedDataset<T> { impl<T: Clone + Default + 'static> ReferencedDataset<T> {
pub fn new() -> ReferencedDataset<T> { pub fn new() -> ReferencedDataset<T> {
ReferencedDataset::<T> { ReferencedDataset::<T> {
actual_data: None, actual_data: None,
@ -121,17 +108,19 @@ impl<T: HasTypeId + Clone + Default> ReferencedDataset<T> {
owner_of_the_set: objectmanager::ObjectId, owner_of_the_set: objectmanager::ObjectId,
) -> Result<(), ()> { ) -> Result<(), ()> {
let owner = object_manager.get_object(owner_of_the_set)?; 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 = core::any::TypeId::of::<T>();
let type_id = temp.get_type_id();
let other_set = match owner.get_set(type_id) { let other_set = match owner.get_set(type_id) {
None => { None => {
return Err(()); return Err(()); //TODO panic? -> should initialize just panic if failing?
} }
Some(set) => set, Some(set) => set,
}; };
//pointer cast is safe because we checked the type_id // let's recheck that owner.get_set did not lie about the type_id
//getting pointer to avoid lifetime check if let Some(other_data) = other_set.get_actual_data().downcast_ref::<T>() {
self.actual_data = Some(other_set.get_actual_data() as *const dyn HasTypeId as *const T); self.actual_data = Some(other_data);
} else {
return Err(());
}
self.mutex = Some(other_set.get_mutex()); self.mutex = Some(other_set.get_mutex());
Ok(()) Ok(())
} }

View File

@ -24,15 +24,13 @@ struct StoreSlot{
} }
impl StoreSlot { impl StoreSlot {
pub fn get_data(&self) -> &[u8] { pub fn get_data(&self) -> &mut [u8] {
check_global_threading_available!(); check_global_threading_available!();
unsafe{&(*self.data)} unsafe{&mut (*self.data)}
} }
pub fn get_all_data(&self) -> &[u8] { pub fn get_all_data(&self) -> &mut [u8] {
check_global_threading_available!(); check_global_threading_available!();
unsafe{&(*self.data)} unsafe{&mut (*self.data)}
} }
} }

View File

@ -55,8 +55,6 @@ struct HandlerData {
y: f32 y: f32
} }
impl datasets::HasTypeId for HandlerData {}
struct Handler { struct Handler {
id: objectmanager::ObjectId, id: objectmanager::ObjectId,
command_queue: queues::MessageQueue<10>, command_queue: queues::MessageQueue<10>,
@ -135,7 +133,7 @@ impl SystemObjectIF for Handler {
} }
impl datasets::DatapoolOwnerIF for Handler { impl datasets::DatapoolOwnerIF for Handler {
fn get_set(&self, type_id: datasets::TypeId) -> Option<&dyn datasets::DataSetIF>{ fn get_set(&self, type_id: core::any::TypeId) -> Option<&dyn datasets::DataSetIF>{
if type_id == self.data.get_type_id(){ if type_id == self.data.get_type_id(){
Some(&self.data) Some(&self.data)
} else { } else {