NonBlockTickBridge

Type Alias NonBlockTickBridge 

Source
pub type NonBlockTickBridge = dyn Fn(Clock, Tick) + Send + Sync;
Expand description

NonBlockTickBridge: a call back to pass the Tick to the instance of clock. Application must provide one when colocated_timer is enabled At the end, normally it’s the receiving portion of application thread, application needs to call Clock::on_tick() to transfer the Tick event. As indicated by the name, the function for TickBridge CANNOT have any blocking operations.

§Examples

use std::thread::{self, JoinHandle, sleep};
use std::sync::{Arc, atomic::{AtomicUsize, Ordering}};
use std::time::Duration;
use log::warn;
use ztimer::{AutoDropTimer, Clock, Tick, Timer};

enum AppMessage {
    MsgTick(Clock, Tick),
    Terminate,
}

let mut app_threads = Vec::<JoinHandle<()>>::new();
let mut txes = Vec::<crossbeam_channel::Sender<AppMessage>>::new();
let count = Arc::new(AtomicUsize::new(0));
let (tx, rx) = crossbeam_channel::bounded::<AppMessage>(1000);

// The application thread is a long-lived thread that processes `AppMessage`s.
let th = thread::Builder::new().name("AppThread".to_string()).spawn(move || {
    while let Ok(m) = rx.recv() {
        match m {
            AppMessage::MsgTick(c, t) => {
                c.on_tick(t);
            },
            AppMessage::Terminate => {
                return;
            },
        }
    }
}).unwrap();
app_threads.push(th);
txes.push(tx.clone());

let cnt = count.clone();

// A non-blocking closure as a TickBridge
let tb = move |c: Clock, t: Tick| {
    cnt.fetch_add(1, Ordering::Relaxed);
    let _ = tx.try_send(AppMessage::MsgTick(c, t));
};
let clk = Clock::new(Some(Box::new(tb))).unwrap();

let _ = Timer::new(clk, Duration::from_secs(1), || { println!("Timer expired") }, "TestTimer".into());

sleep(Duration::from_secs(2));

for tx in txes.iter() {
    let _ = tx.send(AppMessage::Terminate);
}
assert!(count.load(Ordering::Relaxed) > 0);
for h in app_threads {
    h.join().unwrap();
}