Skip to content

节律源

节律源决定“何时触发节点执行”。

你可以把它理解成系统的触发器或时钟源。

Rhythm Trait(当前实现)

pub trait Rhythm {
    type Yield: Send;
    type Feed;
    type Output;
    type Error: Into<RoplatError> + Debug;

    fn drive<N, F, Fut>(
        &mut self, nodes: N, op_domain: F,
    ) -> impl Future<Output = Self::Output> + Send
    where
        N: Send,
        F: FnMut(N, Self::Yield) -> Fut + Send,
        Fut: Future<Output = (Self::Feed, N)> + Send;
}

设计要点

  • 零分配:回调 F 返回编译期已知的 Fut 类型,无 Box::pin 堆分配。
  • Pass-by-Value:节点元组 N 按值传递,回调返回 (Feed, N) 归还所有权。N 实际是可变引用元组(几个指针),移动成本为零。
  • Send 安全Fut: Send 确保 future 可在 tokio::spawn 环境中使用。

注意drive 不要求 N: Sync。节点元组通过 &mut 引用在闭包中逐一解包,不存在并发共享,因此 Send 足矣。

Yield 是节律源每次触发时交给节点域的数据。

内置节律源

  1. SysTimer

  2. 固定周期触发

  3. 产出 EventMeta(包含 timestampdeltajittersequence

  4. CountRhythm

  5. 按次数触发

  6. 可通过 CountHandle 动态调整目标次数

  7. EventRhythm<T>

  8. 基于事件通道触发

  9. EventTrigger<T> 主动投递事件

什么时候选哪一种

  1. 控制回路:优先 SysTimer
  2. 有限步测试:优先 CountRhythm
  3. 外部事件驱动:优先 EventRhythm<T>
  4. 物理仿真步进:优先 SimRhythm(在 rsbullet crate 中,每 tick 先调用 engine.step() 再 yield 给下游)
  5. 离线数据回放 / 批处理:直接使用 Iterator 适配器

实践注意

  1. 你的 drive 循环里不要长期阻塞。
  2. 时间敏感场景应关注 EventMeta.jitter
  3. 节律触发频率要与节点计算耗时匹配,避免持续积压。