8个不稳定版本 (3个破坏性更新)

新功能 0.5.3 2024年8月23日
0.5.2 2024年8月20日
0.5.1 2024年7月29日
0.5.0 2024年4月30日
0.2.0 2024年1月4日

#180 in 算法

Download history 405/week @ 2024-05-03 328/week @ 2024-05-10 433/week @ 2024-05-17 480/week @ 2024-05-24 194/week @ 2024-05-31 261/week @ 2024-06-07 273/week @ 2024-06-14 334/week @ 2024-06-21 78/week @ 2024-06-28 293/week @ 2024-07-05 316/week @ 2024-07-12 638/week @ 2024-07-19 505/week @ 2024-07-26 554/week @ 2024-08-02 647/week @ 2024-08-09 607/week @ 2024-08-16

每月2,418次下载

MIT 许可证

115KB
2.5K SLoC

rex-sm 👑

设计特点

  • 将状态机做成可复用的模块单元
  • 使用其他状态机的状态机知道它们可以使用哪些,但正在使用它们的状态机不知道使用它们的状态机
  • 无任务/线程
  • 并发处理多个状态机
  • 触发其他状态机,等待其完成,然后继续
  • 创建/删除计时器
  • 向状态机组外发送通知
  • 向自身发送事件
  • 从状态机组外接受事件
  • 鼓励将状态机实现表示为 (<State>, <Event>) 格式

灵感来源

概述

StateMachine 首先在 StateMachineManager 中注册,我将简单地称之为 Manager。每次调用 Manager::cycle() 都处理一个单个事件。一个事件对应于运行一个状态机。 Manager 访问 Controller 的内容并对其进行操作。单个 ControllerManager 注册的所有状态机之间共享。

有两种类型的事件 UserEventSystemEventUserEvent 传递给 StateMachine::cycle(),而 SystemEvent 则不传递。 StateMachine::cycle() 接受一个 &mut Controller 和一个 UserEventStateMachine 使用 Controller 中的函数来添加/删除事件到事件队列;除了与计时器相关的函数之外,所有函数都这样做。 SystemEvent 被管理器消费,并用于修改 Controller 的内部或向状态机组外发送数据或通知。

基于节点的状态机管理器(开发中)

目标

  • 将状态机输入处理从特定 当前枚举状态 解耦
  • 表示所有输入都流向同一接收器(管理员的 signal_queue);这允许电梯和过渡处理 统一,从而避免通过 Box<dyn Signal> 导致的类型不透明。

在实际应用中,设计应保证最多只有三条消息流连接到特定的状态机。

I/O

  • 一个 Input(处理外部和内部事件)
Signal {
    id: StateId<K>,
    input: I,
}

两个输出

  • Signal 输出(事件意味着要作为其他状态机的输入处理)
  • Notification 输出(事件意味着要由不是由给定 signal_queue 提供的状态机处理的任何事物处理)

StateMachineManager 拥有

  • 状态存储层(使用 StateStore
  • 输入事件流
  • 状态机处理器

StateMachineManager 负责以下任务

  • Signal 路由到相应的状态机
  • ProcessorContext 注入状态机:这个操作允许状态机并发循环

StateStore 负责以下任务

  • 插入和更新各种状态层次结构
  • 通过在 Arc<Mutex<_>> 容器中保持所有节点树来并发执行操作。

这允许 StateStore 存储能够

  • 通过增加 Arc 计数并插入每个子节点的新条目来通过新的 DashMap 键插入创建多个索引,指向相同的树
  • 允许每个状态树具有独立的内部可变性,解耦无关的状态与资源竞争

基于节点的 TimeoutManager(开发中)

考虑事项

  • 每个 StateId<K> 只有一个活动计时器,状态机不需要跟踪发送到通知的 Operation::Set(Instant::now())。因此,所有计时器都应该可以通过 StateId<K> 索引。
  • 同一 StateId<K> 的新 Operation::Set 应该覆盖旧计时器。
  • 超时应发出与相关状态机相关的 Signal

方法

  • TimeoutManager 实现了一种每滴答轮询的方法来解决超时
  • TimeoutManager 接受两种类型的输入,设置和取消(超时)
  • 超时存储在 TimeoutLedger
  • TimeoutLedger 包含一个 BTreeMap,按 Instant 索引 ID,以及一个 HashMap,按 Instant 索引 ID。这种双重索引允许超时取消操作通过,而无需提供要删除的 Instant

依赖关系

~9-17MB
~200K SLoC