use nodo::{codelet::ScheduleBuilder, prelude::*};
use nodo_runtime::Runtime;
use nodo_std::*;
use std::time::Duration;
struct Bob {
pub ctrl: std::sync::mpsc::SyncSender<RuntimeControl>,
}
#[derive(Config)]
struct BobConfig {
#[mutable]
pub gate_is_open: bool,
}
impl Codelet for Bob {
type Status = DefaultStatus;
type Config = BobConfig;
type Rx = DoubleBufferRx<bool>;
type Tx = ();
type Signals = ();
fn build_bundles(_: &Self::Config) -> (Self::Rx, Self::Tx) {
(
DoubleBufferRx::new(OverflowPolicy::Forget(1), RetentionPolicy::Drop),
(),
)
}
fn start(&mut self, cx: Context<Self>, _: &mut Self::Rx, _: &mut Self::Tx) -> Outcome {
assert_eq!(cx.config.gate_is_open, false);
SUCCESS
}
fn step(&mut self, cx: Context<Self>, rx: &mut Self::Rx, _: &mut Self::Tx) -> Outcome {
if cx.config.gate_is_open {
assert_eq!(rx.pop(), Ok(true));
} else {
self.ctrl
.send(RuntimeControl::Configure(ParameterSet::from_array([
("gate".into(), "is_open".into(), ParameterValue::Bool(true)),
(
"bob".into(),
"gate_is_open".into(),
ParameterValue::Bool(true),
),
])))?;
}
SUCCESS
}
fn stop(&mut self, cx: Context<Self>, _: &mut Self::Rx, _: &mut Self::Tx) -> Outcome {
assert_eq!(cx.config.gate_is_open, true);
SUCCESS
}
}
#[test]
fn test_parameter_gate() -> eyre::Result<()> {
let mut rt = Runtime::new();
let mut alice = RawCloner::new(true).into_instance("alice", ());
let mut gate = ParameterGate::instantiate("gate", ParameterGateConfig { is_open: false });
connect(&mut alice.tx, &mut gate.rx)?;
let mut bob = Bob {
ctrl: rt.tx_control(),
}
.into_instance(
"bob",
BobConfig {
gate_is_open: false,
},
);
connect(&mut gate.tx, &mut bob.rx)?;
rt.add_codelet_schedule(
ScheduleBuilder::new()
.with_period(Duration::from_millis(1))
.with_max_step_count(150)
.with(alice)
.with(gate)
.with(bob),
);
rt.spin();
Ok(())
}