nodo_runtime 0.18.5

Runtime for NODO applications
Documentation
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(())
}