C++ 如何防止boost::statetechart因引发异常而终止

C++ 如何防止boost::statetechart因引发异常而终止,c++,boost-statechart,C++,Boost Statechart,我已经实现了一个继承boost::statechart的状态机。当我调用fsm.process\u event(some\u event())哪个反应会引发异常时,结果是在我使用try-catch-block处理异常后,我的statemachine实例fsm被终止。也就是说,fsm.terminated()返回true。在某些情况下,我不希望它被终止。例如,当我希望状态机抛出异常以通知调用方非处理事件的fsm.process\u event(unrelated\u event()),并将其当前状

我已经实现了一个继承boost::statechart的状态机。当我调用
fsm.process\u event(some\u event())
哪个反应会引发异常时,结果是在我使用try-catch-block处理异常后,我的statemachine实例
fsm
被终止。也就是说,
fsm.terminated()
返回
true
。在某些情况下,我不希望它被终止。例如,当我希望状态机抛出异常以通知调用方非处理事件的
fsm.process\u event(unrelated\u event())
,并将其当前状态保持在事件状态之前

简而言之-如何防止
boost::statechart
在抛出异常后终止,并将其保持在异常之前的状态

示例代码:

namespace sc = boost::statechart;
class State;
struct some_event : public sc::event<some_event> { };

class FSM
    : public sc::state_machine< FSM, State, std::allocator<void>, sc::exception_translator<> >
{
public:
    FSM()
    {
        cout<<"FSM::FSM()"<<endl;
    }
    virtual ~FSM()
    {
        cout<<"FSM::~FSM()"<<endl;
    }
};


class State : public sc::simple_state< State, FSM >
{
public:
    State()
    {
        cout<<"State::State()"<<endl;
    }
    virtual ~State()
    {
        cout<<"State::~State()"<<endl;
    }

    typedef boost::mpl::list<
        sc::custom_reaction< some_event >,
        sc::custom_reaction< sc::exception_thrown >
    > reactions;
    sc::result react( const some_event & e)
    {
        cout<<"State::react( const some_event &)"<<endl;
        throw std::exception();
        return this->discard_event();
    }
    sc::result react( const sc::exception_thrown & e)
    {
        cout<<"State::react( const sc::exception_thrown &)"<<endl;
        throw;
        return this->discard_event();
    }
};

int main()
{
    FSM fsm;
    fsm.initiate();

    try
    {
        fsm.process_event(some_event());
    }
    catch(...)
    {
        cout<<"Exception caught"<<endl;
    }


    if(fsm.terminated())
    {
        cout<<"fsm2 is TERMINATED"<<endl;
    }
    else
    {
        cout<<"fsm2 is RUNNING"<<endl;
    }
    return 0;
}
我希望它输出:

FSM::FSM()
State::State()
State::react( const some_event &)
State::react( const sc::exception_thrown &)
State::~State()
Exception caught
fsm2 is RUNNING

您应该为状态机提供一个自定义异常处理程序。请参见此处的boost文档:

当抛出异常时,状态机不可能知道它是否仍处于有效状态,这就是异常句柄的默认操作是终止sm的原因。您的自定义处理程序可以执行清理/检查,以确保sm处于有效状态,并在不同的庄园中向上传播信息

就我个人而言,我从来没有看到过通过异常从SM传播信息的好理由。这很可能是因为我从未在您的特定领域工作过,但这仍然是我的理性:

如果事件不相关,则忽略它或记录它,同一事件可能在其他状态下相关,而不是当前状态。如果事件无效,即永远不会发生或状态不正确,则为:

  • 如果代码有问题,您应该立即断言并处理该问题
  • 来自包含SM的模块之外的无效输入问题(硬件连续发布了3个断开连接的事件,这永远不会发生等)。在这种情况下,您无法以任何方式在本地模块中正确处理异常,最好的办法是记录问题并切换到灾难性错误状态或只能保留EvReset或其他功能的状态
FSM::FSM()
State::State()
State::react( const some_event &)
State::react( const sc::exception_thrown &)
State::~State()
Exception caught
fsm2 is RUNNING