From 7f6a5c8d29b2bfde0fe173d8d9cec0187d3e4b42 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 9 Jun 2022 16:21:07 +0200 Subject: [PATCH 01/16] 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) -- 2.43.0 From 476b1f6d223088e7d942b13983e8846200de66f6 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 9 Jun 2022 16:21:18 +0200 Subject: [PATCH 02/16] fmt --- src/core/events.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/core/events.rs b/src/core/events.rs index 151b9e4..208d6ab 100644 --- a/src/core/events.rs +++ b/src/core/events.rs @@ -1,11 +1,11 @@ use num::pow; -#[derive (Copy, Clone, PartialEq, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum Severity { INFO = 1, LOW = 2, MEDIUM = 3, - HIGH = 4 + HIGH = 4, } impl TryFrom for Severity { @@ -22,7 +22,7 @@ impl TryFrom for Severity { } } -#[derive (Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug)] pub struct Event { severity: Severity, group_id: u16, @@ -30,7 +30,6 @@ pub struct Event { } 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 /// @@ -44,12 +43,12 @@ impl Event { /// 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 + return None; } Some(Event { severity, group_id, - unique_id + unique_id, }) } @@ -68,7 +67,9 @@ impl Event { } 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 + (((self.severity as u32) << 29) as u32 + | ((self.group_id as u32) << 16) as u32 + | self.unique_id as u32) as u32 } } @@ -78,7 +79,7 @@ impl TryFrom for Event { fn try_from(raw: u32) -> Result { let severity: Option = (((raw >> 29) & 0b111) as u8).try_into().ok(); if severity.is_none() { - return Err(()) + return Err(()); } let group_id = ((raw >> 16) & 0x1FFF) as u16; let unique_id = (raw & 0xFFFF) as u16; @@ -88,8 +89,8 @@ impl TryFrom for Event { #[cfg(test)] mod tests { - use crate::core::events::Severity; use super::Event; + use crate::core::events::Severity; #[test] fn test_events() { @@ -109,4 +110,4 @@ mod tests { assert_eq!(event_conv_back.unique_id(), 0); assert_eq!(event_conv_back.group_id(), 0); } -} \ No newline at end of file +} -- 2.43.0 From d1ff7c5463bce0eaad6f24353c124bbd3094d7cd Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 9 Jun 2022 16:24:50 +0200 Subject: [PATCH 03/16] added additional test --- src/core/events.rs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/core/events.rs b/src/core/events.rs index 208d6ab..42598e4 100644 --- a/src/core/events.rs +++ b/src/core/events.rs @@ -105,9 +105,24 @@ mod tests { 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); + let event = opt_event.unwrap(); + assert_eq!(event.severity(), Severity::INFO); + assert_eq!(event.unique_id(), 0); + assert_eq!(event.group_id(), 0); + + let event = Event::new(Severity::HIGH, 0x1FFF, 0xFFFF).unwrap(); + assert_eq!(event.severity(), Severity::HIGH); + assert_eq!(event.group_id(), 0x1FFF); + assert_eq!(event.unique_id(), 0xFFFF); + let raw_event = event.raw(); + assert_eq!(raw_event, 0x9FFFFFFF); + 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 = opt_event.unwrap(); + assert_eq!(event.severity(), Severity::HIGH); + assert_eq!(event.group_id(), 0x1FFF); + assert_eq!(event.unique_id(), 0xFFFF); } } -- 2.43.0 From 0bd6190055d558aae3c5acd92ff64e55d7e5c6ea Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 9 Jun 2022 16:58:44 +0200 Subject: [PATCH 04/16] basic event sender/receiver test --- src/main.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 7527576..2550b36 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,31 @@ +use std::thread; +use launchpad::core::events::{Event, Severity}; +use std::sync::mpsc::{channel}; fn main() { - println!("hello"); + let test_event_0 = Event::new(Severity::INFO, 0, 0); + let (event_sender, event_receiver) = channel(); + let t0_sender = event_sender.clone(); + let t0 = thread::spawn(move || { + t0_sender.send(test_event_0.unwrap()).expect("Sending event from t0 failed"); + }); + + let test_event_1 = Event::new(Severity::MEDIUM, 1, 8); + let t1 = thread::spawn(move || { + event_sender.send(test_event_1.unwrap()).expect("Sending event from t1 failed"); + }); + + let mut event_cntr = 0; + while event_cntr < 2 { + match event_receiver.recv() { + Ok(event) => { + println!("Received event {:?}", event); + event_cntr += 1; + } + Err(_) => { () + // println!("Received error {:?}", error); + } + } + }; + t0.join().unwrap(); + t1.join().unwrap(); } -- 2.43.0 From 472c8349ac7169e39484a3cc41ef76dbd2d4d3db Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 9 Jun 2022 16:59:38 +0200 Subject: [PATCH 05/16] refactor into functions --- src/main.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2550b36..073a188 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,26 @@ -use std::thread; use launchpad::core::events::{Event, Severity}; -use std::sync::mpsc::{channel}; +use std::sync::mpsc::channel; +use std::thread; + fn main() { + basic_event_test(); +} + +fn basic_event_test() { let test_event_0 = Event::new(Severity::INFO, 0, 0); let (event_sender, event_receiver) = channel(); let t0_sender = event_sender.clone(); let t0 = thread::spawn(move || { - t0_sender.send(test_event_0.unwrap()).expect("Sending event from t0 failed"); + t0_sender + .send(test_event_0.unwrap()) + .expect("Sending event from t0 failed"); }); let test_event_1 = Event::new(Severity::MEDIUM, 1, 8); let t1 = thread::spawn(move || { - event_sender.send(test_event_1.unwrap()).expect("Sending event from t1 failed"); + event_sender + .send(test_event_1.unwrap()) + .expect("Sending event from t1 failed"); }); let mut event_cntr = 0; @@ -21,11 +30,12 @@ fn main() { println!("Received event {:?}", event); event_cntr += 1; } - Err(_) => { () + Err(_) => { + () // println!("Received error {:?}", error); } } - }; + } t0.join().unwrap(); t1.join().unwrap(); } -- 2.43.0 From 30bf2ca667fca677893ae803c7a6baceb98307b4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 9 Jun 2022 17:02:23 +0200 Subject: [PATCH 06/16] some minor improvements --- src/main.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/main.rs b/src/main.rs index 073a188..8c800dc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,15 +25,9 @@ fn basic_event_test() { let mut event_cntr = 0; while event_cntr < 2 { - match event_receiver.recv() { - Ok(event) => { - println!("Received event {:?}", event); - event_cntr += 1; - } - Err(_) => { - () - // println!("Received error {:?}", error); - } + if let Ok(event) = event_receiver.recv() { + println!("Received event {:?}", event); + event_cntr += 1; } } t0.join().unwrap(); -- 2.43.0 From 3d5654a5e6fc7e81836024fefd6ff4e86a3638e0 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 10 Jun 2022 17:55:01 +0200 Subject: [PATCH 07/16] added first event manager --- src/core/events.rs | 22 ++++++++++------- src/main.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/core/events.rs b/src/core/events.rs index 42598e4..561eefc 100644 --- a/src/core/events.rs +++ b/src/core/events.rs @@ -1,6 +1,10 @@ use num::pow; -#[derive(Copy, Clone, PartialEq, Debug)] +pub type GroupId = u16; +pub type UniqueId = u16; +pub type EventRaw = u32; + +#[derive(Copy, Clone, Debug)] pub enum Severity { INFO = 1, LOW = 2, @@ -25,8 +29,8 @@ impl TryFrom for Severity { #[derive(Copy, Clone, Debug)] pub struct Event { severity: Severity, - group_id: u16, - unique_id: u16, + group_id: GroupId, + unique_id: UniqueId, } impl Event { @@ -41,7 +45,7 @@ impl Event { /// 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 { + pub fn new(severity: Severity, group_id: GroupId, unique_id: UniqueId) -> Option { if group_id > (pow::pow(2u8 as u16, 13) - 1) { return None; } @@ -58,22 +62,22 @@ impl Event { self.severity } - pub fn group_id(&self) -> u16 { + pub fn group_id(&self) -> GroupId { self.group_id } - pub fn unique_id(&self) -> u16 { + pub fn unique_id(&self) -> UniqueId { self.unique_id } - pub fn raw(&self) -> u32 { + pub fn raw(&self) -> EventRaw { (((self.severity as u32) << 29) as u32 | ((self.group_id as u32) << 16) as u32 - | self.unique_id as u32) as u32 + | self.unique_id as u32) as EventRaw } } -impl TryFrom for Event { +impl TryFrom for Event { type Error = (); fn try_from(raw: u32) -> Result { diff --git a/src/main.rs b/src/main.rs index 8c800dc..c2f6734 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,63 @@ -use launchpad::core::events::{Event, Severity}; -use std::sync::mpsc::channel; +use launchpad::core::events::{Event, EventRaw, GroupId, Severity}; +use launchpad::core::executable::{Executable, ExecutionType, OpResult}; +use std::collections::HashMap; +use std::sync::mpsc::{channel, Receiver, Sender}; use std::thread; +#[derive(PartialEq, Eq, Hash, Copy, Clone)] +enum ListenerType { + SINGLE(EventRaw), + GROUP(GroupId), +} + +struct Listener { + _ltype: ListenerType, + dest: Sender, +} + +pub struct EventManager { + listeners: HashMap>, + event_receiver: Receiver, +} + +impl Executable for EventManager { + type Error = (); + + fn exec_type(&self) -> ExecutionType { + ExecutionType::Infinite + } + + fn task_name(&self) -> &'static str { + "Event Manager" + } + + fn periodic_op(&mut self, _op_code: i32) -> Result { + if let Ok(event) = self.event_receiver.recv() { + println!("Received event {:?}", event); + } + Ok(OpResult::Ok) + } +} + +impl EventManager { + pub fn subcribe_single(&mut self, event: Event, dest: Sender) { + self.update_listeners(ListenerType::SINGLE(event.raw()), dest); + } + + pub fn subscribe_group(&mut self, group_id: GroupId, dest: Sender) { + self.update_listeners(ListenerType::GROUP(group_id), dest); + } + + fn update_listeners(&mut self, key: ListenerType, dest: Sender) { + if !self.listeners.contains_key(&key) { + self.listeners + .insert(key.clone(), vec![Listener { _ltype: key, dest }]); + } else { + let vec = self.listeners.get_mut(&key).unwrap(); + vec.push(Listener { _ltype: key, dest }); + } + } +} fn main() { basic_event_test(); } -- 2.43.0 From b8d5f75cff14267d6fa65ae77d9851365734f17a Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 10 Jun 2022 18:10:40 +0200 Subject: [PATCH 08/16] new event_man module --- src/core.rs | 1 + src/core/event_man.rs | 67 +++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 59 ++----------------------------------- 3 files changed, 70 insertions(+), 57 deletions(-) create mode 100644 src/core/event_man.rs diff --git a/src/core.rs b/src/core.rs index 6ee7941..10ab1e7 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,3 +1,4 @@ pub mod events; +pub mod event_man; pub mod executable; pub mod objects; diff --git a/src/core/event_man.rs b/src/core/event_man.rs new file mode 100644 index 0000000..08e27f3 --- /dev/null +++ b/src/core/event_man.rs @@ -0,0 +1,67 @@ +use std::collections::HashMap; +use std::sync::mpsc::{Receiver, Sender}; +use crate::core::events::{Event, EventRaw, GroupId}; + +#[derive(PartialEq, Eq, Hash, Copy, Clone)] +enum ListenerType { + Single(EventRaw), + Group(GroupId), +} + +struct Listener { + _ltype: ListenerType, + dest: Sender, +} + +pub struct EventManager { + listeners: HashMap>, + event_receiver: Receiver, +} + +impl EventManager { + pub fn subcribe_single(&mut self, event: Event, dest: Sender) { + self.update_listeners(ListenerType::Single(event.raw()), dest); + } + + pub fn subscribe_group(&mut self, group_id: GroupId, dest: Sender) { + self.update_listeners(ListenerType::Group(group_id), dest); + } + + fn update_listeners(&mut self, key: ListenerType, dest: Sender) { + if let std::collections::hash_map::Entry::Vacant(e) = self.listeners.entry(key) { + e.insert(vec![Listener { _ltype: key, dest }]); + } else { + let vec = self.listeners.get_mut(&key).unwrap(); + vec.push(Listener { _ltype: key, dest }); + } + } + + pub fn periodic_op(&mut self) { + if let Ok(event) = self.event_receiver.recv() { + println!("Received event {:?}", event); + for (ltype, listener_list) in self.listeners.iter() { + match ltype { + ListenerType::Single(raw_event) => { + if event.raw() == *raw_event { + for listener in listener_list { + listener.dest.send(event).expect("Sending event failed"); + } + } + } + ListenerType::Group(group_id) => { + if event.group_id() == *group_id { + for listener in listener_list { + listener.dest.send(event).expect("Sending event failed"); + } + } + } + } + } + } + } +} + +#[cfg(test)] +mod tests { + +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c2f6734..58906a2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,63 +1,8 @@ -use launchpad::core::events::{Event, EventRaw, GroupId, Severity}; -use launchpad::core::executable::{Executable, ExecutionType, OpResult}; -use std::collections::HashMap; -use std::sync::mpsc::{channel, Receiver, Sender}; +use launchpad::core::events::{Event, Severity}; +use std::sync::mpsc::channel; use std::thread; -#[derive(PartialEq, Eq, Hash, Copy, Clone)] -enum ListenerType { - SINGLE(EventRaw), - GROUP(GroupId), -} -struct Listener { - _ltype: ListenerType, - dest: Sender, -} - -pub struct EventManager { - listeners: HashMap>, - event_receiver: Receiver, -} - -impl Executable for EventManager { - type Error = (); - - fn exec_type(&self) -> ExecutionType { - ExecutionType::Infinite - } - - fn task_name(&self) -> &'static str { - "Event Manager" - } - - fn periodic_op(&mut self, _op_code: i32) -> Result { - if let Ok(event) = self.event_receiver.recv() { - println!("Received event {:?}", event); - } - Ok(OpResult::Ok) - } -} - -impl EventManager { - pub fn subcribe_single(&mut self, event: Event, dest: Sender) { - self.update_listeners(ListenerType::SINGLE(event.raw()), dest); - } - - pub fn subscribe_group(&mut self, group_id: GroupId, dest: Sender) { - self.update_listeners(ListenerType::GROUP(group_id), dest); - } - - fn update_listeners(&mut self, key: ListenerType, dest: Sender) { - if !self.listeners.contains_key(&key) { - self.listeners - .insert(key.clone(), vec![Listener { _ltype: key, dest }]); - } else { - let vec = self.listeners.get_mut(&key).unwrap(); - vec.push(Listener { _ltype: key, dest }); - } - } -} fn main() { basic_event_test(); } -- 2.43.0 From 3bd8c58340169c7b898f6f54b43ce2893e6d3a50 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 10 Jun 2022 18:47:56 +0200 Subject: [PATCH 09/16] kind of awkward, but maybe there is no other way.. --- src/core/event_man.rs | 53 +++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/src/core/event_man.rs b/src/core/event_man.rs index 08e27f3..68b6c54 100644 --- a/src/core/event_man.rs +++ b/src/core/event_man.rs @@ -1,5 +1,4 @@ use std::collections::HashMap; -use std::sync::mpsc::{Receiver, Sender}; use crate::core::events::{Event, EventRaw, GroupId}; #[derive(PartialEq, Eq, Hash, Copy, Clone)] @@ -8,60 +7,74 @@ enum ListenerType { Group(GroupId), } -struct Listener { +pub trait EventRecipient { + type Error; + fn send_to(&mut self, event: Event) -> Result<(), Self::Error>; +} + +struct Listener { _ltype: ListenerType, - dest: Sender, + dest: Box>, } -pub struct EventManager { - listeners: HashMap>, - event_receiver: Receiver, +pub trait ReceivesEvent { + fn receive(&mut self) -> Option; } -impl EventManager { - pub fn subcribe_single(&mut self, event: Event, dest: Sender) { + +pub struct EventManager { + listeners: HashMap>>, + event_receiver: dyn ReceivesEvent, +} + +impl EventManager { + pub fn subcribe_single(&mut self, event: Event, dest: impl EventRecipient + 'static) { self.update_listeners(ListenerType::Single(event.raw()), dest); } - pub fn subscribe_group(&mut self, group_id: GroupId, dest: Sender) { + pub fn subscribe_group(&mut self, group_id: GroupId, dest: impl EventRecipient + 'static) { self.update_listeners(ListenerType::Group(group_id), dest); } - fn update_listeners(&mut self, key: ListenerType, dest: Sender) { - if let std::collections::hash_map::Entry::Vacant(e) = self.listeners.entry(key) { - e.insert(vec![Listener { _ltype: key, dest }]); + fn update_listeners (&mut self, key: ListenerType, dest: impl EventRecipient + 'static) { + if !self.listeners.contains_key(&key) { + self.listeners.insert(key, vec![Listener { _ltype: key, dest: Box::new(dest) }]); } else { let vec = self.listeners.get_mut(&key).unwrap(); - vec.push(Listener { _ltype: key, dest }); + vec.push(Listener { _ltype: key, dest: Box::new(dest) }); } } - pub fn periodic_op(&mut self) { - if let Ok(event) = self.event_receiver.recv() { + pub fn periodic_op(&mut self) -> Result<(), E> { + if let Some(event) = self.event_receiver.receive() { println!("Received event {:?}", event); - for (ltype, listener_list) in self.listeners.iter() { + for (ltype, listener_list) in self.listeners.iter_mut() { match ltype { ListenerType::Single(raw_event) => { if event.raw() == *raw_event { - for listener in listener_list { - listener.dest.send(event).expect("Sending event failed"); + for listener in listener_list.iter_mut() { + listener.dest.send_to(event)?; } } } ListenerType::Group(group_id) => { if event.group_id() == *group_id { - for listener in listener_list { - listener.dest.send(event).expect("Sending event failed"); + for listener in listener_list.iter_mut() { + listener.dest.send_to(event)?; } } } } } } + Ok(()) } } #[cfg(test)] mod tests { + #[test] + fn basic_test() { + } } \ No newline at end of file -- 2.43.0 From b283c661555b003cf1775fdf3bb3100e5b288c02 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 10 Jun 2022 18:54:30 +0200 Subject: [PATCH 10/16] some minor improvements --- src/core/event_man.rs | 18 +++++++++++------- src/core/events.rs | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/core/event_man.rs b/src/core/event_man.rs index 68b6c54..720f99f 100644 --- a/src/core/event_man.rs +++ b/src/core/event_man.rs @@ -37,37 +37,41 @@ impl EventManager { } fn update_listeners (&mut self, key: ListenerType, dest: impl EventRecipient + 'static) { - if !self.listeners.contains_key(&key) { - self.listeners.insert(key, vec![Listener { _ltype: key, dest: Box::new(dest) }]); + if let std::collections::hash_map::Entry::Vacant(e) = self.listeners.entry(key) { + e.insert(vec![Listener { _ltype: key, dest: Box::new(dest) }]); } else { let vec = self.listeners.get_mut(&key).unwrap(); vec.push(Listener { _ltype: key, dest: Box::new(dest) }); } } - pub fn periodic_op(&mut self) -> Result<(), E> { + pub fn handle_one_event(&mut self) -> Result<(), E> { + let mut status = Ok(()); if let Some(event) = self.event_receiver.receive() { - println!("Received event {:?}", event); for (ltype, listener_list) in self.listeners.iter_mut() { match ltype { ListenerType::Single(raw_event) => { if event.raw() == *raw_event { for listener in listener_list.iter_mut() { - listener.dest.send_to(event)?; + if let Err(e) = listener.dest.send_to(event) { + status = Err(e); + } } } } ListenerType::Group(group_id) => { if event.group_id() == *group_id { for listener in listener_list.iter_mut() { - listener.dest.send_to(event)?; + if let Err(e) = listener.dest.send_to(event) { + status = Err(e); + } } } } } } } - Ok(()) + status } } diff --git a/src/core/events.rs b/src/core/events.rs index 561eefc..db09f11 100644 --- a/src/core/events.rs +++ b/src/core/events.rs @@ -4,7 +4,7 @@ pub type GroupId = u16; pub type UniqueId = u16; pub type EventRaw = u32; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, PartialEq, Debug)] pub enum Severity { INFO = 1, LOW = 2, -- 2.43.0 From e813d7d51c4dc9af681709ebe019938e31f11408 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 10 Jun 2022 19:22:05 +0200 Subject: [PATCH 11/16] adding first unittest --- src/core.rs | 2 +- src/core/event_man.rs | 95 +++++++++++++++++++++++++++++++++++++------ src/main.rs | 1 - 3 files changed, 83 insertions(+), 15 deletions(-) diff --git a/src/core.rs b/src/core.rs index 10ab1e7..bb36e7e 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,4 +1,4 @@ -pub mod events; pub mod event_man; +pub mod events; pub mod executable; pub mod objects; diff --git a/src/core/event_man.rs b/src/core/event_man.rs index 720f99f..895249e 100644 --- a/src/core/event_man.rs +++ b/src/core/event_man.rs @@ -1,5 +1,5 @@ -use std::collections::HashMap; use crate::core::events::{Event, EventRaw, GroupId}; +use std::collections::HashMap; #[derive(PartialEq, Eq, Hash, Copy, Clone)] enum ListenerType { @@ -7,41 +7,60 @@ enum ListenerType { Group(GroupId), } -pub trait EventRecipient { +pub trait EventListener { type Error; fn send_to(&mut self, event: Event) -> Result<(), Self::Error>; } struct Listener { _ltype: ListenerType, - dest: Box>, + dest: Box>, } -pub trait ReceivesEvent { +pub trait ReceivesAllEvent { fn receive(&mut self) -> Option; } - pub struct EventManager { listeners: HashMap>>, - event_receiver: dyn ReceivesEvent, + event_receiver: Box, } impl EventManager { - pub fn subcribe_single(&mut self, event: Event, dest: impl EventRecipient + 'static) { + pub fn new(event_receiver: Box) -> Self { + EventManager { + listeners: HashMap::new(), + event_receiver, + } + } + pub fn subcribe_single(&mut self, event: Event, dest: impl EventListener + 'static) { self.update_listeners(ListenerType::Single(event.raw()), dest); } - pub fn subscribe_group(&mut self, group_id: GroupId, dest: impl EventRecipient + 'static) { + pub fn subscribe_group( + &mut self, + group_id: GroupId, + dest: impl EventListener + 'static, + ) { self.update_listeners(ListenerType::Group(group_id), dest); } - fn update_listeners (&mut self, key: ListenerType, dest: impl EventRecipient + 'static) { + fn update_listeners( + &mut self, + key: ListenerType, + dest: impl EventListener + 'static, + ) { if let std::collections::hash_map::Entry::Vacant(e) = self.listeners.entry(key) { - e.insert(vec![Listener { _ltype: key, dest: Box::new(dest) }]); + e.insert(vec![Listener { + _ltype: key, + dest: Box::new(dest), + }]); } else { let vec = self.listeners.get_mut(&key).unwrap(); - vec.push(Listener { _ltype: key, dest: Box::new(dest) }); + vec.push(Listener { + _ltype: key, + dest: Box::new(dest), + }); } } @@ -77,8 +96,58 @@ impl EventManager { #[cfg(test)] mod tests { + use super::{EventListener, ReceivesAllEvent}; + use crate::core::event_man::EventManager; + use crate::core::events::{Event, Severity}; + use std::fmt::Error; + use std::sync::mpsc::{channel, Receiver, SendError, Sender}; + + struct EventReceiver { + mpsc_receiver: Receiver, + } + impl ReceivesAllEvent for EventReceiver { + fn receive(&mut self) -> Option { + self.mpsc_receiver.recv().ok() + } + } + + struct MpscEventSenderQueue { + mpsc_sender: Sender, + } + + impl EventListener for MpscEventSenderQueue { + type Error = SendError; + + fn send_to(&mut self, event: Event) -> Result<(), Self::Error> { + self.mpsc_sender.send(event) + } + } + #[test] fn basic_test() { - + let (event_sender, manager_queue) = channel(); + let event_man_receiver = EventReceiver { + mpsc_receiver: manager_queue, + }; + let mut event_man: EventManager> = + EventManager::new(Box::new(event_man_receiver)); + let sender_0 = event_sender.clone(); + let event_grp_0 = Event::new(Severity::INFO, 0, 0).unwrap(); + let event_grp_1_0 = Event::new(Severity::HIGH, 1, 0).unwrap(); + let event_grp_1_1 = Event::new(Severity::MEDIUM, 1, 32).unwrap(); + let event_grp_1_2 = Event::new(Severity::LOW, 1, 43).unwrap(); + let event_grp_2 = Event::new(Severity::HIGH, 32, 0).unwrap(); + let (single_event_sender, single_event_receiver) = channel(); + let single_event_listener = MpscEventSenderQueue { + mpsc_sender: single_event_sender, + }; + let (group_event_sender, group_event_receiver) = channel(); + let group_event_listener = MpscEventSenderQueue { + mpsc_sender: group_event_sender, + }; + event_man.subscribe_group(event_grp_1_0.group_id(), group_event_listener); + event_sender.send(event_grp_0).expect("Send error occured"); + // let event = single_event_receiver.recv().expect("Error receiving event"); + // println!("{:?}", event); } -} \ No newline at end of file +} diff --git a/src/main.rs b/src/main.rs index 58906a2..8c800dc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,6 @@ use launchpad::core::events::{Event, Severity}; use std::sync::mpsc::channel; use std::thread; - fn main() { basic_event_test(); } -- 2.43.0 From 8c94c5300d629103077461b0adb011d9c429f12e Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Sat, 11 Jun 2022 01:59:39 +0200 Subject: [PATCH 12/16] finished event man tests --- .idea/runConfigurations/Test.xml | 1 - src/core/event_man.rs | 242 +++++++++++++++++++++++++------ src/core/events.rs | 2 +- 3 files changed, 202 insertions(+), 43 deletions(-) diff --git a/.idea/runConfigurations/Test.xml b/.idea/runConfigurations/Test.xml index 9f2b663..15edb2f 100644 --- a/.idea/runConfigurations/Test.xml +++ b/.idea/runConfigurations/Test.xml @@ -7,7 +7,6 @@