- 定义消息队列,用来缓存来不及处理的消息;
- 定义预处理,用来判断消息的有效性、是否需要缓存、延后处理等,预处理和状态机当前的状态无关;
- 定义主处理,主处理应该是一个状态机栈,栈顶是当前的状态机上下文,其中存储当前状态机的状态等- 信息,根据消息ID,在当前状态机的对应状态处理表中,查找是否有消息ID对应的处理函数,如果有,则进入处理函数进行处理,如果没有,则消息将被丢弃(或者在预处理判断后进行缓存);
- 定义后处理,当一层状态机退栈后,执行一次后处理,包括处理所有的缓存消息、内部消息(状态机可以自己给自己发内部消息,用来自己主动触发一些流程);
- 所有处理的方式均为消息ID==》对应的处理函数,类似于查表的机制;
- 单线程状态机不应该有计算密集型的任务,通常将计算密集型任务分发出去做异步计算处理;
- 多层状态机:通常专门处理流程可以起2层甚至3层状态机,这样做的好处是分类更加明确,主要针对一些逻辑较为复杂的任务,例如建立连接,涉及到和远程的异步交互,可以专门起一个层二状态机,或者系统配置,可能涉及到和不同的模块交互,也可以专门起一个层二状态机。起层二状态机的方法是初始化一个新的状态机上下文对象,将其压栈即可。如果处理完毕,要退出层二装填机,则执行退栈即可;
- 状态机之间的交互:通常一个模块一个状态机,模块之间采用统一的消息机制模拟交互,即SendMsg和RecvMsg。SendMsg本质上是将发送的消息给调度线程,调度线程将消息实体投递到对应pid的模块的消息队列中。RecvMsg是pop一次本模块的消息队列;
- 线程分配:可以多个状态机共享一个线程,也可以每个状态机一个线程。如果多个状态机共享一个线程,需要确保每个状态机的每一个处理函数都是简单的,非计算密集型的,否则会影响到其他状态机的消息处理,导致消息队列爆满,无法再接收消息;
- 消息队列实现:通常采用RingBuffer无锁队列;
[C/C++]状态机设计
最新推荐文章于 2024-05-19 22:52:45 发布