gpt4 book ai didi

c++ - "generalized"有限状态机实现

转载 作者:可可西里 更新时间:2023-11-01 16:37:37 26 4
gpt4 key购买 nike

我经常需要实现一个能够根据用户命令切换其行为的对象。例如,这可能是连接到 PC 并由用户通过 GUI 控制的类表示设备的情况。更一般地说,设备必须独立存在,有自己的操作调度。 enter image description here由于我想从特定设备类中“提取”此行为以增强代码重用,因此我在这里提出了一个使用 Qt 的模板化有限状态机类。我还在 A 类中报告了一个示例用法。您(比我更有经验的程序员 :) 对此有何看法?这是设计这样一个类的“正确”方法吗?是否存在性能问题?

template < class Base,
typename T,
class ThreadPolicy>
class FSM
{
public:
typedef bool (Base::*my_func)();
struct SState {
SState(){}
SState(const T& id_arg,
const T& next_arg,
const T& error_arg,
const QList<T>& branches_arg,
const my_func& op_arg) :
id(id_arg),
next(next_arg),
error(error_arg),
branches(branches_arg),
op(op_arg)
{}
T id; // state ID
T next; // next state
T error; // in case of error
QList<T> branches; // allowed state switching from current
my_func op; // operation associated with current state
};
typedef QMap<T ,SState> SMap;
bool switchState(const T& ns){
return _checkAllowed(ns);
}
bool addState(const T& id, const SState& s){
return _register(id, s);
}
protected:

void _loop(Base* ptr){
if ((ptr->*m_states[m_state].op)()) {
ThreadPolicy::Lock();
if(m_externalSwitch){
m_externalSwitch = false;
ThreadPolicy::Unlock();
return;
}
m_state = m_states[m_state].next;
ThreadPolicy::Unlock();
} else {
ThreadPolicy::Lock();
if(m_externalSwitch){
m_externalSwitch = false;
ThreadPolicy::Unlock();
return;
}
m_state = m_states[m_state].error;
ThreadPolicy::Unlock();
}
}
bool _checkAllowed(const T& cmd){
if (!m_states[m_state].branches.contains(cmd)) { return false;}
ThreadPolicy::Lock();
m_state = cmd;
m_externalSwitch = true;
ThreadPolicy::Unlock();
return true;
}

bool _register(const SState& s){
if(m_states.find(s.id) != m_states.end()) { return false; } // state with same ID already exist
m_states[s.id] = s; // add the new state to the map
return true;
}
SMap m_states; // map states to Baseclass methods
T m_state; // holds my current state
bool m_externalSwitch; // check if user request a state switch
};

class A :
public QObject,
public FSM< A, QString, MultiThreaded >
{
Q_OBJECT
A(){
// SState startState; myState.branches << "start" << "stop";
_register(SState("start",
"start",
"stop",QStringList(("start","stop")),
&A::_doStart));
_register(SState("stop",
"stop",
"stop",QStringList(("stop","start")),
&A::_doStop));
}

private slots:
void run(){
for(;;){
_loop(this);
QCoreApplication::processEvents();
}
}
private:
bool _doStart(){ return true;}
bool _doStop(){ return true;}

};

最佳答案

A. What do you ( more experienced programmers than me :) think about that? Is it the "correct" way to design such a class? Are there performance issues ?

好的!我粗略地查看了您的设计,对于通用 FSM 框架,我真的感觉不太好。这太狭窄了,无法在更广泛的上下文中使用。批评的一些要点:

  1. 你依赖于 Qt :( ; 至少你应该使用 C++ STL 组件来实现你的实现细节。
  2. 你的状态应该是独立的(专门的)类,实现行为直接。 FSM 类本身应该是独立的(尤其是不执行)他们的行为。
  3. 您不支持更复杂的状态图,包括子状态(机器)/复合状态,并发 FSM 路径(fork,结)、事件状态(重复的异步 do 操作)、...

一般来说,我建议遵循 GoF State Pattern用于 FSM 实现。对于非常简单的状态图 switch(event) case <event>: changeState(newState)可能就够了。但是将事件呈现为 FSM 的方法条目,并将这些委托(delegate)给当前状态类实例,使整个构造更加灵活。考虑随特定事件一起出现的可选参数,您需要为这些扩展您的状态机设计。

一般来说,您使用 CRTP 的方法对于您的状态机来说是个好主意,但对于您所演示的内容,简单的动态多态性(使用虚拟成员函数)也可以很好地工作。

关于性能问题,不要认为您会在当前环境中遇到问题,但这完全取决于您要部署的位置和环境。

我想推荐你看看我的状态机类模板框架 STTCL ,它提供了符合 UML 2.0 的状态机的各种基于 C++ 模板的方面,遵循已经提到的 GoF 状态模式。

关于c++ - "generalized"有限状态机实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20720195/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com