系列文章目录
目录需要自己手动添加
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
目录
前言
由于本人在开发一个新的视频模式识别产品中,会涉及到较多的各种状态变化,例如视频源经常由于网络原因或者视频源本生原因引起视频无法读取,读取完成后识别会涉及到多种场景,这些对应场景有些需要保存留作凭证,并同时上传第三方平台等,原有的状态管理太过庞杂造成而难于维护,故开始研究boost下的两个有限状态机以解决当前项目中问。理论上的材料完全依照官网英文材料(由于本人翻译及英文能力有限错误之处请读者谅解)。此文只要根据官网文档翻译而来,并结合笔者本人实际项目中的应用提供部分代码示例。Meta State Machine后续简称元状态机或者(MSM)——版权备注,此文档,未取得原作者授权,此文只记录本人学习理解过程。Chapter 3. Tutorial - 1.79.0https://www.boost.org/doc/libs/1_79_0/libs/msm/doc/HTML/ch03.html#d0e325
1.设计(design)
元状态机(以下简称状态机或者MSM)分为前端(front-ends)和后端(back-ends)。目前只有一个后端,前端有三个状态机语言(模型)前后端接口详见(前后端接口)。
首先前端采用动作适配(MPL book)连接状态和状态机。第二采用仿函数。第三采用boost的eUML——boost针对UML的验证性项目,使用了boost.Proto、Boost.Type和元编程技术增加可读性。eUML和仿函数的前端为用户提供各种动作列表方式。
2.基本前端(basic front-ends)
这个基本前端从MPL book项目延申而来,其提供一个用行方式提供状态转换表,动作(Actions)和状态转换条件(guards)采用方法实现(转换实体指针)。基本前端提供简单接口确保简单定义状态机的hi使用,但要实现更复杂的状体机比较困难。
2.1.最简使用例程
2.1.1状态图
转自原文
2.1.2 图例说明
1、此例演示一个播放器的操作按钮作为一个状态机实例。此状态表示当前CD播放器按钮有:1)打开/关闭——放置cd的抽屉;2)停止——停止播放;3)暂停——暂停播放;4)播放;
原教程代码请参见libs/msm/doc/HTML/examples/SimpleTutorial.cpp - 1.79.0
2.1.3源代码解释:
1、事件定义(详细见2.2事件定义)
1)首先定义操作事件结构体:play(播放)、end_pause(结束暂停(继续))、 stop(停止)、pause(暂停)、open_close(开关cd盒);2)定义一个内部事件:cd_detected(cd歌曲信息检查,通过这个事件可以定义检查后,显示这些歌曲信息)内部事件,包含事件本身信息,可以为后续事件使用和处理,且可以通过结构构造函数初始化(如下):
struct play {};
.....
struct cd_detected {
cd_detected(std::string name, DiskTypeEnum diskType)
: name(name),disc_type(diskType) {}
std::string name;
DiskTypeEnum disc_type;
};
2、定义前端状态机类从源代码--player_ 如下
struct player_ : public msm::front::state_machine_def<player_>
{
.......
void no_transition(Event const& e, FSM&,int state)
{
std::cout << "no transition from state " << state
<< " on event " << typeid(e).name() << std::endl;
}
};
在这个基本前端中包含以下要素代码:
1)状态定义:状态Empty\Open\Stoped\Playing状态包含出入口状态on_entry()/on_exit();其中stopped状态还包含状态机指针方法。Paused状态没有出入口(on_entry()/on_exit();)(详细见2.4)Stoped状态采用set_sm_ptr(),目前这个方法被废弃,不建议使用,建议用后续仿函数方式实现。
// The list of FSM states
struct Empty : public msm::front::state<>
{
// every (optional) entry/exit methods get the event passed.
template <class Event,class FSM>
void on_entry(Event const&,FSM& ) {std::cout << "entering: Empty" << std::endl;}
template <class Event,class FSM>
void on_exit(Event const&,FSM& ) {std::cout << "leaving: Empty" << std::endl;} };
struct Open : public msm::front::state<>
{
template <class Event,class FSM>
void on_entry(Event const& ,FSM&) {std::cout << "entering: Open" << std::endl;}
template <class Event,class FSM>
void on_exit(Event const&,FSM& ) {std::cout << "leaving: Open" << std::endl;}
};
// sm_ptr still supported but deprecated as functors are a much better way to do the same thing
struct Stopped : public msm::front::state<msm::front::default_base_state,msm::front::sm_ptr>
{
template <class Event,class FSM>
void on_entry(Event const& ,FSM&) {std::cout << "entering: Stopped" << std::endl;}
template <class Event,class FSM>
void on_exit(Event const&,FSM& ) {std::cout << "leaving: Stopped" << std::endl;}
void set_sm_ptr(player_* pl) {
m_player=pl;
}
player_* m_player;
};
struct Playing : public msm::front::state<>
{
template <class Event,class FSM>
void on_entry(Event const&,FSM& ) {std::cout << "entering: Playing" << std::endl;}
template <class Event,class FSM>
void on_exit(Event const&,FSM& ) {std::cout << "leaving: Playing" << std::endl;}
};
// state not defining any entry or exit
struct Paused : public msm::front::state<>
{
};
3、定义初始状态
// the initial state of the player SM. Must be defined
typedef Empty initial_state;
4、状态转换函数;守护(条件函数)(具体定义见