use stakker::*;
use std::time::{Duration, Instant};
struct Light {
start: Instant,
on: bool,
}
impl Light {
pub fn init(cx: CX![]) -> Option<Self> {
let start = cx.now();
Some(Self { start, on: false })
}
pub fn set(&mut self, cx: CX![], on: bool) {
self.on = on;
let time = cx.now() - self.start;
println!(
"{:04}.{:03} Light on: {}",
time.as_secs(),
time.subsec_millis(),
on
);
}
pub fn query(&self, _cx: CX![], ret: Ret<bool>) {
ret!([ret], self.on);
}
}
struct Flasher {
light: Actor<Light>,
interval: Duration,
count: usize,
}
impl Flasher {
pub fn init(cx: CX![], light: Actor<Light>, interval: Duration, count: usize) -> Option<Self> {
call!([cx], switch(true));
Some(Self {
light,
interval,
count,
})
}
pub fn switch(&mut self, cx: CX![], on: bool) {
call!([self.light], set(on));
self.count -= 1;
if self.count != 0 {
after!(self.interval, [cx], switch(!on));
} else {
cx.stop();
}
let ret = ret_some_to!([cx], recv_state(self.count) as (bool));
call!([self.light], query(ret));
}
fn recv_state(&self, _: CX![], count: usize, state: bool) {
println!(" (at count {} received: {})", count, state);
}
}
fn main() {
let mut stakker0 = Stakker::new(Instant::now());
let stakker = &mut stakker0;
let light = actor!(stakker, Light::init(), ret_nop!());
let _flasher = actor!(
stakker,
Flasher::init(light.clone(), Duration::from_secs(1), 6),
ret_shutdown!(stakker)
);
stakker.run(Instant::now(), false);
while stakker.not_shutdown() {
let maxdur = stakker.next_wait_max(Instant::now(), Duration::from_secs(60), false);
std::thread::sleep(maxdur);
stakker.run(Instant::now(), false);
}
}