Skip to content

Commit

Permalink
[larry-robotics#3] Remove the SignalHandler from all public examples …
Browse files Browse the repository at this point in the history
…and introduce `Elk::wait()` has replacement
  • Loading branch information
elfenpiff committed Dec 12, 2023
1 parent c00ab5d commit 6c7f042
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 46 deletions.
31 changes: 16 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ while a subscriber efficiently receives and prints the data.

```rust
use elkodon::prelude::*;
use elkodon_bb_posix::signal::SignalHandler;

const CYCLE_TIME: Duration = Duration::from_secs(1);

fn main() -> Result<(), Box<dyn std::error::Error>> {
let service_name = ServiceName::new(b"My/Funk/ServiceName")?;
Expand All @@ -110,12 +111,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {

let publisher = service.publisher().create()?;

while !SignalHandler::termination_requested() {
while let ElkEvent::Tick = Elk::wait(CYCLE_TIME) {
let sample = publisher.loan_uninit()?;
let sample = sample.write_payload(1234);
publisher.send(sample)?;

std::thread::sleep(std::time::Duration::from_secs(1));
}

Ok(())
Expand All @@ -126,7 +125,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {

```rust
use elkodon::prelude::*;
use elkodon_bb_posix::signal::SignalHandler;

const CYCLE_TIME: Duration = Duration::from_secs(1);

fn main() -> Result<(), Box<dyn std::error::Error>> {
let service_name = ServiceName::new(b"My/Funk/ServiceName")?;
Expand All @@ -137,12 +137,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {

let subscriber = service.subscriber().create()?;

while !SignalHandler::termination_requested() {
while let ElkEvent::Tick = Elk::wait(CYCLE_TIME) {
while let Some(sample) = subscriber.receive()? {
println!("received: {:?}", *sample);
}

std::thread::sleep(std::time::Duration::from_secs(1));
}

Ok(())
Expand Down Expand Up @@ -173,7 +171,8 @@ This minimal example showcases an event notification between two processes.

```rust
use elkodon::prelude::*;
use elkodon_bb_posix::signal::SignalHandler;

const CYCLE_TIME: Duration = Duration::from_secs(1);

fn main() -> Result<(), Box<dyn std::error::Error>> {
let event_name = ServiceName::new(b"MyEventName")?;
Expand All @@ -185,12 +184,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let notifier = event.notifier().create()?;

let mut counter: u64 = 0;
while !SignalHandler::termination_requested() {
while let ElkEvent::Tick = Elk::wait(CYCLE_TIME) {
counter += 1;
notifier.notify_with_custom_event_id(EventId::new(counter))?;

println!("Trigger event with id {} ...", counter);
std::thread::sleep(std::time::Duration::from_secs(1));
}

Ok(())
Expand All @@ -201,7 +199,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {

```rust
use elkodon::prelude::*;
use elkodon_bb_posix::signal::SignalHandler;

const CYCLE_TIME: Duration = Duration::from_secs(1);

fn main() -> Result<(), Box<dyn std::error::Error>> {
let event_name = ServiceName::new(b"MyEventName")?;
Expand All @@ -212,9 +211,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {

let mut listener = event.listener().create()?;

while !SignalHandler::termination_requested() {
for event_id in listener.timed_wait(std::time::Duration::from_secs(1))? {
println!("event was triggered with id: {:?}", event_id);
while let ElkEvent::Tick = Elk::wait(Duration::ZERO) {
if let Ok(events) = listener.timed_wait(CYCLE_TIME) {
for event_id in events {
println!("event was triggered with id: {:?}", event_id);
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions elkodon/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ version = { workspace = true }
repository = { workspace = true }
edition = { workspace = true }

[features]
# Enables https://crates.io/crates/log as default logger
logger_log = []
# Enables https://crates.io/crates/tracing as default logger
logger_tracing = []

[dependencies]
elkodon_bb_container = { workspace = true }
elkodon_bb_system_types = { workspace = true }
Expand Down
96 changes: 96 additions & 0 deletions elkodon/src/elk.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//! # Example
//!
//! ## Simple Event Loop
//!
//! ```no_run
//! use elkodon::prelude::*;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! const CYCLE_TIME: Duration = Duration::from_secs(1);
//!
//! while let ElkEvent::Tick = Elk::wait(CYCLE_TIME) {
//! // your algorithm in here
//! }
//! # Ok(())
//! # }
//! ```
//!
//! ## Advanced Event Loop
//!
//! ```no_run
//! use elkodon::prelude::*;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! const CYCLE_TIME: Duration = Duration::from_secs(1);
//!
//! loop {
//! match Elk::wait(CYCLE_TIME) {
//! ElkEvent::Tick => {
//! println!("entered next cycle");
//! }
//! ElkEvent::TerminationRequest => {
//! println!("User pressed CTRL+c, terminating");
//! break;
//! }
//! ElkEvent::InterruptSignal => {
//! println!("Someone send an interrupt signal ...");
//! }
//! }
//! }
//! # Ok(())
//! # }
//! ```
use core::time::Duration;
use elkodon_bb_log::fatal_panic;
use elkodon_bb_posix::clock::{nanosleep, NanosleepError};
use elkodon_bb_posix::signal::SignalHandler;

/// A complete list of all events that can occur in the main event loop, [`Elk::wait()`].
pub enum ElkEvent {
Tick,
TerminationRequest,
InterruptSignal,
}

/// The main event loop handling mechanism.
#[derive(Debug)]
pub struct Elk {
_priv: (),
}

impl Elk {
fn get_instance() -> &'static Self {
static INSTANCE: Elk = Elk { _priv: () };
&INSTANCE
}

fn wait_impl(&self, cycle_time: Duration) -> ElkEvent {
if SignalHandler::termination_requested() {
return ElkEvent::TerminationRequest;
}

match nanosleep(cycle_time) {
Ok(()) => {
if SignalHandler::termination_requested() {
ElkEvent::TerminationRequest
} else {
ElkEvent::Tick
}
}
Err(NanosleepError::InterruptedBySignal(_)) => ElkEvent::InterruptSignal,
Err(v) => {
fatal_panic!(from self,
"Failed to wait with cycle time {:?} in main event look, caused by ({:?}).",
cycle_time, v);
}
}
}

/// Waits until an event has received. It returns
/// [`ElkEvent::Tick`] when the `cycle_time` has passed, otherwise the other event that
/// can occur.
pub fn wait(cycle_time: Duration) -> ElkEvent {
Self::get_instance().wait_impl(cycle_time)
}
}
33 changes: 18 additions & 15 deletions elkodon/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@
//!
//! ```no_run
//! use elkodon::prelude::*;
//! use elkodon_bb_posix::signal::SignalHandler;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! const CYCLE_TIME: Duration = Duration::from_secs(1);
//! let service_name = ServiceName::new(b"My/Funk/ServiceName")?;
//!
//! // create our port factory by creating or opening the service
Expand All @@ -59,12 +59,10 @@
//!
//! let subscriber = service.subscriber().create()?;
//!
//! while !SignalHandler::termination_requested() {
//! while let ElkEvent::Tick = Elk::wait(CYCLE_TIME) {
//! while let Some(sample) = subscriber.receive()? {
//! println!("received: {:?}", *sample);
//! }
//!
//! std::thread::sleep(std::time::Duration::from_secs(1));
//! }
//! # Ok(())
//! # }
Expand All @@ -74,9 +72,9 @@
//!
//! ```no_run
//! use elkodon::prelude::*;
//! use elkodon_bb_posix::signal::SignalHandler;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! const CYCLE_TIME: Duration = Duration::from_secs(1);
//! let service_name = ServiceName::new(b"My/Funk/ServiceName").unwrap();
//!
//! // create our port factory by creating or opening the service
Expand All @@ -86,12 +84,10 @@
//!
//! let publisher = service.publisher().create()?;
//!
//! while !SignalHandler::termination_requested() {
//! while let ElkEvent::Tick = Elk::wait(CYCLE_TIME) {
//! let sample = publisher.loan_uninit()?;
//! let sample = sample.write_payload(1234);
//! publisher.send(sample)?;
//!
//! std::thread::sleep(std::time::Duration::from_secs(1));
//! }
//!
//! # Ok(())
Expand All @@ -108,9 +104,9 @@
//!
//! ```no_run
//! use elkodon::prelude::*;
//! use elkodon_bb_posix::signal::SignalHandler;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! const CYCLE_TIME: Duration = Duration::from_secs(1);
//! let event_name = ServiceName::new(b"MyEventName")?;
//!
//! let event = zero_copy::Service::new(&event_name)
Expand All @@ -119,9 +115,11 @@
//!
//! let mut listener = event.listener().create()?;
//!
//! while !SignalHandler::termination_requested() {
//! for event_id in listener.timed_wait(std::time::Duration::from_secs(1))? {
//! println!("event was triggered with id: {:?}", event_id);
//! while let ElkEvent::Tick = Elk::wait(Duration::ZERO) {
//! if let Ok(events) = listener.timed_wait(CYCLE_TIME) {
//! for event_id in events {
//! println!("event was triggered with id: {:?}", event_id);
//! }
//! }
//! }
//!
Expand All @@ -133,9 +131,9 @@
//!
//! ```no_run
//! use elkodon::prelude::*;
//! use elkodon_bb_posix::signal::SignalHandler;
//!
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! const CYCLE_TIME: Duration = Duration::from_secs(1);
//! let event_name = ServiceName::new(b"MyEventName")?;
//!
//! let event = zero_copy::Service::new(&event_name)
Expand All @@ -145,12 +143,11 @@
//! let notifier = event.notifier().create()?;
//!
//! let mut counter: u64 = 0;
//! while !SignalHandler::termination_requested() {
//! while let ElkEvent::Tick = Elk::wait(CYCLE_TIME) {
//! counter += 1;
//! notifier.notify_with_custom_event_id(EventId::new(counter))?;
//!
//! println!("Trigger event with id {} ...", counter);
//! std::thread::sleep(std::time::Duration::from_secs(1));
//! }
//!
//! # Ok(())
Expand Down Expand Up @@ -258,6 +255,9 @@ mod compiletests;
/// Handles elkodons global configuration
pub mod config;

/// Central instance that handles all incoming events, the event loop
pub mod elk;

pub(crate) mod message;

/// The ports or communication endpoints of elkodon
Expand All @@ -277,9 +277,12 @@ pub mod service;

/// Loads a meaninful subset to cover 90% of the elkodon communication use cases.
pub mod prelude {
pub use crate::elk::Elk;
pub use crate::elk::ElkEvent;
pub use crate::port::event_id::EventId;
pub use crate::service::{
process_local, service_name::ServiceName, zero_copy, Details, Service,
};
pub use core::time::Duration;
pub use elkodon_bb_container::semantic_string::SemanticString;
}
11 changes: 7 additions & 4 deletions examples/examples/event/listener.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use elkodon::prelude::*;
use elkodon_bb_posix::signal::SignalHandler;

const CYCLE_TIME: Duration = Duration::from_secs(1);

fn main() -> Result<(), Box<dyn std::error::Error>> {
let event_name = ServiceName::new(b"MyEventName")?;
Expand All @@ -10,9 +11,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {

let mut listener = event.listener().create()?;

while !SignalHandler::termination_requested() {
for event_id in listener.timed_wait(std::time::Duration::from_secs(1))? {
println!("event was triggered with id: {:?}", event_id);
while let ElkEvent::Tick = Elk::wait(Duration::ZERO) {
if let Ok(events) = listener.timed_wait(CYCLE_TIME) {
for event_id in events {
println!("event was triggered with id: {:?}", event_id);
}
}
}

Expand Down
6 changes: 3 additions & 3 deletions examples/examples/event/notifier.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use elkodon::prelude::*;
use elkodon_bb_posix::signal::SignalHandler;

const CYCLE_TIME: Duration = Duration::from_secs(1);

fn main() -> Result<(), Box<dyn std::error::Error>> {
let event_name = ServiceName::new(b"MyEventName")?;
Expand All @@ -11,12 +12,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let notifier = event.notifier().create()?;

let mut counter: u64 = 0;
while !SignalHandler::termination_requested() {
while let ElkEvent::Tick = Elk::wait(CYCLE_TIME) {
counter += 1;
notifier.notify_with_custom_event_id(EventId::new(counter))?;

println!("Trigger event with id {} ...", counter);
std::thread::sleep(std::time::Duration::from_secs(1));
}

println!("exit ... ");
Expand Down
Loading

0 comments on commit 6c7f042

Please sign in to comment.