forked from ROMEO/obsw
Dataset using introspection is better
This commit is contained in:
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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];
|
||||||
|
Reference in New Issue
Block a user