2014-02-20 63 views
0

我已經實現了一個繼承boost :: statechart的狀態機。當我打電話給fsm.process_event(some_event())哪個反應預計會拋出異常時,事實證明,在我用try-catch塊處理異常之後,我的statemachine實例fsm被終止。即,fsm.terminated()返回true。在某些情況下,我不希望它終止。就像我希望狀態機拋出異常,通知調用者fsm.process_event(irrelevant_event())未處理事件並在事件狀態之前保持其當前狀態。如何防止boost :: statetechart因拋出異常而終止

總之 - 我怎樣才能防止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 

回答

0

你應該提供一個自定義的異常處理程序到你的狀態機。請參閱此處的boost文檔:http://www.boost.org/doc/libs/1_55_0/libs/statechart/doc/tutorial.html#ExceptionHandling

當拋出異常時,狀態機不可能知道它是否仍處於有效狀態,這就是爲什麼異常句柄的默認操作是終止sm的原因。您的自定義處理程序可以執行清理/檢查以確保sm處於有效狀態並以不同的方式向上傳播信息。

就我個人而言,我從來沒有見過很好的理由通過例外傳播信息。這可能很有可能是因爲我從來沒有在你的特定領域工作,但這些都不是我的理性:

如果事件不相關,那麼忽略它或記錄它,這個相同的事件可能與另一個國家相關不是現在的那個。如果事件是無效的,即不可能發生,或者有不正確的狀態,則有兩種情況:

  • 與您的代碼有問題,你應該堅持並立即處理
  • 的問題,超出無效輸入的問題包含SM的模塊(硬件連續發佈3個斷開連接的事件,這絕不會是等)。在這種情況下,您無法以任何方式在本地模塊中正確處理異常,最好的辦法是記錄問題並切換到CatastrophicErrorState或只能使用EvReset或其他內容的東西。
相關問題