From 7f6a5c8d29b2bfde0fe173d8d9cec0187d3e4b42 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 9 Jun 2022 16:21:07 +0200 Subject: [PATCH] started event abstraction --- Cargo.lock | 112 +++++++++++++++++++++++++++++----------- Cargo.toml | 2 +- src/core/events.rs | 113 ++++++++++++++++++++++++++++++++++++++++- src/core/executable.rs | 2 +- src/core/objects.rs | 20 +++++++- 5 files changed, 213 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b0b631b..04224db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1e66e1779f5b1440f1a58220ba3b3ded4427175f0a9fb8d7066521f8b4e8f2b" dependencies = [ "atomic-option", - "crossbeam-channel 0.4.4", + "crossbeam-channel", "num_cpus", "parking_lot_core", ] @@ -38,12 +38,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - [[package]] name = "cloudabi" version = "0.0.3" @@ -59,20 +53,10 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" dependencies = [ - "crossbeam-utils 0.7.2", + "crossbeam-utils", "maybe-uninit", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.8", -] - [[package]] name = "crossbeam-utils" version = "0.7.2" @@ -80,17 +64,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ "autocfg", - "cfg-if 0.1.10", - "lazy_static", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" -dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "lazy_static", ] @@ -108,7 +82,7 @@ name = "launchpad" version = "0.1.0" dependencies = [ "bus", - "crossbeam-channel 0.5.4", + "num", "thiserror", ] @@ -130,6 +104,82 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" +[[package]] +name = "num" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fbc387afefefd5e9e39493299f3069e14a140dd34dc19b4c1c1a8fddb6a790" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" +dependencies = [ + "autocfg", + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + [[package]] name = "num_cpus" version = "1.13.1" @@ -146,7 +196,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", "cloudabi", "libc", "redox_syscall", diff --git a/Cargo.toml b/Cargo.toml index 116c94f..b443f50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,4 +8,4 @@ edition = "2021" [dependencies] thiserror = "1.0" bus = "2.2.3" -crossbeam-channel = "0.5.4" \ No newline at end of file +num = "0.4" diff --git a/src/core/events.rs b/src/core/events.rs index 00c3847..151b9e4 100644 --- a/src/core/events.rs +++ b/src/core/events.rs @@ -1,3 +1,112 @@ -pub struct Event { - pub event_id: u32, +use num::pow; + +#[derive (Copy, Clone, PartialEq, Debug)] +pub enum Severity { + INFO = 1, + LOW = 2, + MEDIUM = 3, + HIGH = 4 } + +impl TryFrom for Severity { + type Error = (); + + fn try_from(value: u8) -> Result { + match value { + x if x == Severity::INFO as u8 => Ok(Severity::INFO), + x if x == Severity::LOW as u8 => Ok(Severity::LOW), + x if x == Severity::MEDIUM as u8 => Ok(Severity::MEDIUM), + x if x == Severity::HIGH as u8 => Ok(Severity::HIGH), + _ => Err(()), + } + } +} + +#[derive (Copy, Clone, Debug)] +pub struct Event { + severity: Severity, + group_id: u16, + unique_id: u16, +} + +impl Event { + + /// Generate an event. The raw representation of an event has 32 bits. + /// If the passed group ID is invalid (too large), None wil be returned + /// + /// # Parameter + /// + /// `severity`: Each event has a [severity][Severity]. The raw value of the severity will + /// be stored inside the uppermost 3 bits of the raw event ID + /// `group_id`: Related events can be grouped using a group ID. The group ID will occupy the + /// next 13 bits after the severity. Therefore, the size is limited by dec 8191 hex 0x1FFF. + /// `unique_id`: Each event has a unique 16 bit ID occupying the last 16 bits of the + /// raw event ID + pub fn new(severity: Severity, group_id: u16, unique_id: u16) -> Option { + if group_id > (pow::pow(2u8 as u16, 13) - 1) { + return None + } + Some(Event { + severity, + group_id, + unique_id + }) + } + + /// Retrieve the severity of an event. Returns None if that severity bit field of the raw event + /// ID is invalid + pub fn severity(&self) -> Severity { + self.severity + } + + pub fn group_id(&self) -> u16 { + self.group_id + } + + pub fn unique_id(&self) -> u16 { + self.unique_id + } + + pub fn raw(&self) -> u32 { + (((self.severity as u32) << 29) as u32 | ((self.group_id as u32) << 16) as u32 | self.unique_id as u32) as u32 + } +} + +impl TryFrom for Event { + type Error = (); + + fn try_from(raw: u32) -> Result { + let severity: Option = (((raw >> 29) & 0b111) as u8).try_into().ok(); + if severity.is_none() { + return Err(()) + } + let group_id = ((raw >> 16) & 0x1FFF) as u16; + let unique_id = (raw & 0xFFFF) as u16; + Event::new(severity.unwrap(), group_id, unique_id).ok_or(()) + } +} + +#[cfg(test)] +mod tests { + use crate::core::events::Severity; + use super::Event; + + #[test] + fn test_events() { + let event = Event::new(Severity::INFO, 0, 0).unwrap(); + assert_eq!(event.severity(), Severity::INFO); + assert_eq!(event.unique_id(), 0); + assert_eq!(event.group_id(), 0); + + let raw_event = event.raw(); + assert_eq!(raw_event, 0x20000000); + let conv_from_raw = Event::try_from(raw_event); + assert!(conv_from_raw.is_ok()); + let opt_event = conv_from_raw.ok(); + assert!(opt_event.is_some()); + let event_conv_back = opt_event.unwrap(); + assert_eq!(event_conv_back.severity(), Severity::INFO); + assert_eq!(event_conv_back.unique_id(), 0); + assert_eq!(event_conv_back.group_id(), 0); + } +} \ No newline at end of file diff --git a/src/core/executable.rs b/src/core/executable.rs index 68935c1..a1eb853 100644 --- a/src/core/executable.rs +++ b/src/core/executable.rs @@ -80,7 +80,7 @@ pub fn exec_sched_single< /// /// * `executable_vec`: Vector of executable objects /// * `task_freq`: Optional frequency of task. Required for periodic and fixed cycle tasks -/// * `op_code`: Operation code which is passed to the executable task periodic_op call +/// * `op_code`: Operation code which is passed to the executable task [operation call][Executable::periodic_op] /// * `termination`: Optional termination handler which can cancel threads with a broadcast pub fn exec_sched_multi< T: Executable + Send + 'static + ?Sized, diff --git a/src/core/objects.rs b/src/core/objects.rs index 0da10e4..1306abe 100644 --- a/src/core/objects.rs +++ b/src/core/objects.rs @@ -8,6 +8,8 @@ pub struct ObjectId { name: &'static str, } +/// Each object which is stored inside the [object manager][ObjectManager] needs to implemented +/// this trait pub trait SystemObject { fn as_any(&self) -> &dyn Any; fn get_object_id(&self) -> &ObjectId; @@ -16,7 +18,21 @@ pub trait SystemObject { pub trait ManagedSystemObject: SystemObject + Any {} -/// Helper module to manage multiple SystemObject by mapping them using an ObjectId +/// Helper module to manage multiple [ManagedSystemObjects][ManagedSystemObject] by mapping them +/// using an [object ID][ObjectId] +/// +/// # Example +/// ```rs +/// let mut obj_manager = ObjectManager::default(); +/// let expl_obj_id = ObjectId { +/// id: 0, +/// name: "Example 0", +/// }; +/// let example_obj = ExampleSysObj::new(expl_obj_id, 42); +/// obj_manager.insert(Box::new(example_obj)) +/// let obj_back_casted: Option<&ExampleSysObj> = obj_manager.get(&expl_obj_id); +/// let expl_obj_back_casted = obj_back_casted.unwrap(); +/// ``` pub struct ObjectManager { obj_map: HashMap>, } @@ -53,6 +69,8 @@ impl ObjectManager { Ok(init_success) } + /// Retrieve an object stored inside the manager. The type to retrieve needs to be explicitly + /// passed as a generic parameter pub fn get(&self, key: &ObjectId) -> Option<&T> { self.obj_map .get(key)