
有限状态机:表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。它对数字系统的设计具有十分重要的作用。常见的计算机就是使用有限状态机作为计算模型的;电脑游戏设计中也经常使用有限状态机模型。本文就讲讲一个状态机的 C++实现。
有限状态机
什么是有限状态机?
简单说就是作一件事可能会经过多个不同状态的转换, 转换依赖于在不同时间发生的不同事件来触发, 举个例子,比如 TCP 的状态转换图, 在实现上就可以用 FSM.

传统的实现方案
if…else : 搞一大堆 if else, 一个函数写很长很长…
swich…case : 也搞一大堆一个函数写很长很长…
FSM 的实现方案
根据具体的业务需要, 将业务的处理流程定义为一个状态机, 此状态机中存在以下必要元素
1.根据业务需要, 拆解抽象出若干个不同状态 State, 并确定此状态机的初始状态;
2 根据实现需要, 抽象出用于触发状态转换的事件 Event;
3.为了处理一个 Event, 需要定义状态的转换过程 Transition;
4.状态机要先判断当前所处的状态是否与当前发生的 Event 匹配(注意: 相同的状态可能同时匹配多个 Event)。
用张简图来说明一下

1.MachineSet 可以同时管理多个 Machine;
2.外部触发的 Event 进入到 MachineSet 的事件队列;
3.事件队列里的 Event 被顺序处理, 被 Dispatch 到 match 的 Machine;
4.Machine 根据当前的所处的 state 和 Event 类型来判断当前 Event 是否有效;
5.如果上面(4)中的 Event 有效, 则进行状态转换;
6.状态转换具体来说涉及到三个回调函数:
6.1 当前 state 离开, 是第一个回调,需要使用者根据实际需要处理;
6.2 trasition 这个转换过程, 是第二个回调;
6.3 新 state 的进入, 是第三个回调;
一个简单的状态机,差不多就是上面这些内容, 剩下的就是用程序语言把它实现出来了;
FSM 的 C++ 实现
一个用 C++11 实现的 FSM 的代码
实现简介:
主要就是按 deamo 里的思路, 封装了以下几个模块
MachineSet,
Machine,
Event,
Transition,
Predicate
对于 Event 的处理, 提供两种方案:
1.直接使用 MachineSet 提供的 StartBackground, 开启一个 work thread, 在这个 work thread 中不断从存储 event 的 fifo 队列中获取 event 后 dispatch 到各个 machine;
2.不使用 MachineSet 提供的 event fifo, 实现自己的 MachineSetHandler, 将其实例注册到 MachineSet, 从 event 的派发;
一个具体的实现
我们来使用上面的 FSM 的实现来模拟一个用户登陆的场景;
定义用到的 Event 和几种不同的事件类型

定义用到的状态机, 从 kuafu::StateMachine 继承, 其中包括用过的几种 state 和 transition

在 Birth()函数中构造 state 和 transition, Birth()是 StateMachine 的一个虚函数, 每个用户实现的 Machine 都需要实现它:

创建 MachineSet, 并开始 event 处理线程

创建用户定义的 Machine, 设置初始状态

设置 state 和 transition 相应的回调

模拟 event 发生:

相关源码:
本文转载自公众号 360 云计算(ID:hulktalk)。
原文链接:
https://mp.weixin.qq.com/s/BVaOWSzUsGldbmQk9QZgFw
评论