Dataset using introspection is better

This commit is contained in:
2024-02-08 18:03:09 +01:00
parent 8e8b3f3da4
commit 139c6a0356
5 changed files with 49 additions and 81 deletions

View File

@ -1,21 +1,5 @@
use core::any::Any;
use crate::check_global_threading_available;
use super::objectmanager::SystemObjectIF;
use super::{mutex, objectmanager}; use super::{mutex, objectmanager};
use crate::check_global_threading_available;
pub trait DatapoolOwnerIF {
fn get_set(&self, _type_id: core::any::TypeId) -> Option<&dyn DataSetIF> {
None
}
}
pub trait DataSetIF {
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 core::any::Any;
fn get_mutex(&self) -> mutex::RawMutex;
}
pub struct OwnedDataset<T: Clone> { pub struct OwnedDataset<T: Clone> {
actual_data: T, actual_data: T,
@ -28,22 +12,6 @@ pub struct ReferencedDataset<T: Clone> {
mutex: Option<mutex::RawMutex>, mutex: Option<mutex::RawMutex>,
} }
impl<T: Clone + Default + 'static> DataSetIF for OwnedDataset<T> {
fn get_type_id(&self) -> core::any::TypeId {
core::any::TypeId::of::<T>()
}
fn get_actual_data(&self) -> &dyn core::any::Any {
// only return pointer when threading
check_global_threading_available!();
&self.actual_data
}
fn get_mutex(&self) -> mutex::RawMutex {
return self.mutex.clone();
}
}
impl<T: Clone + Default> OwnedDataset<T> { impl<T: Clone + Default> OwnedDataset<T> {
pub fn new() -> OwnedDataset<T> { pub fn new() -> OwnedDataset<T> {
OwnedDataset::<T> { OwnedDataset::<T> {
@ -86,17 +54,10 @@ impl<T: Clone + Default + 'static> ReferencedDataset<T> {
} }
pub fn read(&mut self) -> Result<T, ()> { pub fn read(&mut self) -> Result<T, ()> {
let _mutex_guard = match &self.mutex { let mutex = self.mutex.as_ref().ok_or(())?;
None => return Err(()), let _guard = mutex.take()?;
Some(mutex) => match mutex.take() { let pointer = self.actual_data.ok_or(())?;
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 // we are only allowed to use the pointer during threading
check_global_threading_available!(); check_global_threading_available!();
Ok(unsafe { (*pointer).clone() }) Ok(unsafe { (*pointer).clone() })
@ -108,20 +69,21 @@ impl<T: Clone + Default + 'static> 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 type_id = core::any::TypeId::of::<T>(); owner.for_each_member_return(&mut |x, _| {
let other_set = match owner.get_set(type_id) { self.try_initialize_from(x.downcast_ref()?);
None => { None
return Err(()); //TODO panic? -> should initialize just panic if failing? });
}
Some(set) => set,
};
// let's recheck that owner.get_set() did not lie about the type_id
if let Some(other_data) = other_set.get_actual_data().downcast_ref::<T>() {
self.actual_data = Some(other_data);
} else {
return Err(());
}
self.mutex = Some(other_set.get_mutex());
Ok(()) Ok(())
} }
fn try_initialize_from(&mut self, other: &OwnedDataset<T>) {
// TODO check some id to allow the other to own multiple
// instances of <T>. Otherwise, this will select the last
// one.
// if !self.id == other.id {
// return
// }
self.actual_data = Some(&other.actual_data);
self.mutex = Some(other.mutex.clone());
}
} }

View File

@ -7,4 +7,5 @@ pub mod tasks;
pub mod objectmanager; pub mod objectmanager;
pub mod datasets; pub mod datasets;
pub mod store; pub mod store;
mod mutex; mod mutex;
pub mod introspection;

View File

@ -5,7 +5,7 @@ pub trait ObjectManager<'a> {
fn get_object(&self, id: ObjectId) -> Result<&'a dyn SystemObjectIF, ()>; fn get_object(&self, id: ObjectId) -> Result<&'a dyn SystemObjectIF, ()>;
} }
pub trait SystemObjectIF: tasks::ExecutableObjectIF + datasets::DatapoolOwnerIF { pub trait SystemObjectIF: tasks::ExecutableObjectIF + introspection::Introspection {
fn get_id(&self) -> ObjectId; fn get_id(&self) -> ObjectId;
fn initialize(&mut self, object_manager: &dyn ObjectManager) -> Result<(), ()>; fn initialize(&mut self, object_manager: &dyn ObjectManager) -> Result<(), ()>;
fn get_command_queue(&self) -> queues::MessageQueueSender; fn get_command_queue(&self) -> queues::MessageQueueSender;

View File

@ -39,6 +39,7 @@ impl<'a> Store<'a> {
} }
} }
// TODO needs to be able to be uninitialized as it should be usable as member
// A smart pointer to a Store protecting insane (static) pointer usage // A smart pointer to a Store protecting insane (static) pointer usage
// only works during threading, panics otherwise // only works during threading, panics otherwise
struct StoreAccessor { struct StoreAccessor {

View File

@ -3,12 +3,11 @@
//TODO os errors in API calls //TODO os errors in API calls
//TODO look into a pattern for late initialized stuff, currently using Option (can we make it compile time safe?) //TODO look into a pattern for late initialized stuff, currently using Option (can we make it compile time safe?)
mod fsrc; pub mod fsrc;
use core::fmt::Write; use core::fmt::Write;
use core::panic::PanicInfo; use core::panic::PanicInfo;
use fsrc::datasets::{DataSetIF, DatapoolOwnerIF};
use fsrc::objectmanager::SystemObjectIF; use fsrc::objectmanager::SystemObjectIF;
use fsrc::*; use fsrc::*;
@ -49,16 +48,16 @@ extern "C" fn rust_main() {
sifln!("Mission done"); sifln!("Mission done");
} }
#[derive (Copy, Clone, Default)] #[derive(Copy, Clone, Default)]
struct HandlerData { struct HandlerData {
x: u32, x: u32,
y: f32 y: f32,
} }
struct Handler { struct Handler {
id: objectmanager::ObjectId, id: objectmanager::ObjectId,
command_queue: queues::MessageQueue<10>, command_queue: queues::MessageQueue<10>,
data: datasets::OwnedDataset<HandlerData> data: datasets::OwnedDataset<HandlerData>,
} }
struct HandlerSender { struct HandlerSender {
@ -66,10 +65,9 @@ struct HandlerSender {
other_handler: objectmanager::ObjectId, other_handler: objectmanager::ObjectId,
cycle: u8, cycle: u8,
other_handler_queue: queues::MessageQueueSender, other_handler_queue: queues::MessageQueueSender,
other_data: datasets::ReferencedDataset<HandlerData> other_data: datasets::ReferencedDataset<HandlerData>,
} }
impl Handler { impl Handler {
fn handle_message(&self, message: queues::Message) { fn handle_message(&self, message: queues::Message) {
match message { match message {
@ -132,17 +130,23 @@ impl SystemObjectIF for Handler {
} }
} }
impl datasets::DatapoolOwnerIF for Handler { impl introspection::Introspection for HandlerSender {
fn get_set(&self, type_id: core::any::TypeId) -> Option<&dyn datasets::DataSetIF>{ fn for_each_member(&self, f: &mut dyn FnMut(&dyn core::any::Any, &str) -> ()) {}
if type_id == self.data.get_type_id(){
Some(&self.data) fn for_each_member_return(&self, f: &mut dyn FnMut(&dyn core::any::Any, &str) -> Option<()>) {}
} else {
None
}
}
} }
impl DatapoolOwnerIF for HandlerSender {} impl introspection::Introspection for Handler {
fn for_each_member(&self, f: &mut dyn FnMut(&dyn core::any::Any, &str) -> ()) {
(*f)(&self.command_queue, "command_queue");
(*f)(&self.data, "data");
}
fn for_each_member_return(&self, f: &mut dyn FnMut(&dyn core::any::Any, &str) -> Option<()>) {
(*f)(&self.command_queue, "command_queue");
(*f)(&self.data, "data");
}
}
impl SystemObjectIF for HandlerSender { impl SystemObjectIF for HandlerSender {
fn get_command_queue(&self) -> crate::fsrc::queues::MessageQueueSender { fn get_command_queue(&self) -> crate::fsrc::queues::MessageQueueSender {
@ -154,14 +158,14 @@ impl SystemObjectIF for HandlerSender {
} }
fn initialize(&mut self, object_manager: &dyn objectmanager::ObjectManager) -> Result<(), ()> { fn initialize(&mut self, object_manager: &dyn objectmanager::ObjectManager) -> Result<(), ()> {
let other_handler_maybe = object_manager.get_object(self.other_handler); let other_handler_maybe = object_manager.get_object(self.other_handler);
let other_handler = let other_handler = match other_handler_maybe {
match other_handler_maybe {
Ok(other) => other, Ok(other) => other,
Err(_) => return Err(()), Err(_) => return Err(()),
}; };
self.other_handler_queue = other_handler.get_command_queue(); self.other_handler_queue = other_handler.get_command_queue();
self.other_data.initialize(object_manager, self.other_handler)?; self.other_data
.initialize(object_manager, self.other_handler)?;
Ok(()) Ok(())
} }
} }
@ -172,14 +176,14 @@ fn mission() {
let mut h1 = Handler { let mut h1 = Handler {
id: 1, id: 1,
command_queue: queues::MessageQueue::new(), command_queue: queues::MessageQueue::new(),
data: datasets::OwnedDataset::new() data: datasets::OwnedDataset::new(),
}; };
let mut h2 = HandlerSender { let mut h2 = HandlerSender {
id: 2, id: 2,
other_handler: 3, other_handler: 3,
cycle: 0, cycle: 0,
other_handler_queue: queues::MessageQueueSender::new(), other_handler_queue: queues::MessageQueueSender::new(),
other_data: datasets::ReferencedDataset::new() other_data: datasets::ReferencedDataset::new(),
}; };
let array: &mut [&mut dyn objectmanager::SystemObjectIF] = &mut [&mut h1]; let array: &mut [&mut dyn objectmanager::SystemObjectIF] = &mut [&mut h1];