【问题标题】:How to prevent boost::statetechart from terminating due to exception thrown如何防止 boost::statetechart 由于抛出异常而终止
【发布时间】:2014-02-20 09:47:35
【问题描述】:

我已经实现了一个继承 boost::statechart 的状态机。当我调用fsm.process_event( some_event() ) 哪个反应预计会引发异常时,结果证明在我使用try-catch 块处理异常后,我的状态机实例fsm 被终止。也就是说,fsm.terminated() 返回true。在某些情况下,我不希望它被终止。就像我希望状态机抛出异常以通知调用者 fsm.process_event( irrelevant_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 TERMINATED

我希望它输出:

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

【问题讨论】:

    标签: c++ boost-statechart


    【解决方案1】:

    您应该为您的状态机提供一个自定义异常处理程序。在此处查看 boost 文档:http://www.boost.org/doc/libs/1_55_0/libs/statechart/doc/tutorial.html#ExceptionHandling

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

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

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

    • 你的代码有问题,你应该立即断言并处理这个问题
    • 来自包含 SM 的模块之外的无效输入的问题(硬件连续发布 3 个断开连接的事件,这永远不可能等等)。在这种情况下,您无法以任何方式在本地模块中正确处理异常,最好的办法是记录问题并切换到 CatastrophicErrorState 或只能留下 EvReset 或其他东西的东西。

    【讨论】:

      猜你喜欢
      • 2018-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-07
      • 2013-02-09
      • 2022-01-01
      • 1970-01-01
      相关资源
      最近更新 更多