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();
}