状态机——(1)

前言

本周 状态机实现库 有两大变化:

  • 状态机各部分功能抽象为接口
  • 添加或修改以下功能:
    • 状态机允许初始状态悬空和修改初始状态
    • 添加线性状态机构建工具
    • 添加看门狗工具

本文主要介绍新功能的使用。

新功能使用说明

构建线性状态机

所谓线性状态机指的是状态有顺序并基于执行次数或外部条件按顺序调度的一类状态机。其本质与其他可执行后可自动跳转的状态机并无不同,因此库只需提供一个方便的构建器即可。

当前提供的 DSL 构建器:

1
2
3
4
5
6
7
val `for` = linearStateMachine {
var i = 0
once { i = 0 }
call(20) { println(++i) }
delay { time = 1; unit = SECONDS }
once { println("hello world!") }
}

once 指定的代码块将执行 1 次。可以通过 call 设置代码块的执行次数。还可以通过 forever 设置代码块无限循环(可以通过看门狗退出)。delay 用于在两个状态之间制造间隔。

状态指定的顺序就是状态执行的顺序。reset 可要求状态机回到初始状态,初始状态是无法修改的。

看门狗

有时状态执行较慢,或者状态的离开条件因为某些原因迟迟无法满足,我们希望状态机在最终无望转移时仍能继续执行下去,此时可以使用看门狗。构造看门狗时需要指定看门狗作用的状态机、其起始状态、目标状态和等待的时间。当调用看门狗的 start 方法后,看门狗将启动。当等待时间消耗殆尽,状态机会启动一次检查,如果当前状态是指定的起始状态,环境有满足目标状态的进入条件,就不再检查起始状态的离开条件,直接驱动一次跳转。

由于其强制跳转操作依赖于状态机的支持,看门狗作用的状态机必须实现 IExternalTransferable<T>

示例代码:

1
2
3
4
5
val init = state {
val dog = Watchdog(this@stateMachine, null, null, 5, SECONDS)
before = { dog.start(); ACCEPT }
doing = { i = 0 }
}

此状态机将在 init 状态初次执行 5s 后直接结束。

状态机接口

这一部分不详述,有兴趣可看类图:

class diagram