Hi,
I have root fsm which has a sub-fsm. In the sub-fsm there are some
useful actions that can throw exceptions.
For that case any fsm has its own exception handler that translates
exception into a generic error event:
template
void exception_caught(Event&, OtherFSM& fsm, std::exception& e)
{
fsm.process_event(error());
}
I faced a strange problem: if an exception occurs, the sub successfully
goes to Error state, the root has no_transition
I use boost 1.55 and VS2013
there are transition tables:
Sub:
Error & Finish - exit points
A_Exception action generates exception
typedef ::boost::mpl::vector initial_state;
struct /*sub*/ transition_table : public ::boost::mpl::vector <
// Start Event Next Action Guard
//
+----------------+---------------+------------------+----------------------+--------------------------+
Row < Empty , none , Waiting , none
, none >,
Row < Waiting , process , Process , A_Exception
, none >,
Row < Process , none , Finish , none
, none >,
//
+----------------+---------------+------------------+----------------------+--------------------------+
Row < AllOk , error , Error , none
, none >
//
+----------------+---------------+------------------+----------------------+--------------------------+
{};
Root:
struct S
{
typedef SubFsm::exit_pt Error;
typedef SubFsm::exit_pt Finish;
};
struct /*root*/ transition_table : public ::boost::mpl::vector <
// Start Event Next Action Guard
//
+----------------+---------------+------------------+----------------------+--------------------------+
Row < Empty , init , Initial , none , none
>,
Row < Initial , sub , SubFsm , none , none
>,
//
+----------------+---------------+------------------+----------------------+--------------------------+
Row < S::Error , error , Error , none , none
>,
Row < S::Finish , none , Initial , none , none
>
//
+----------------+---------------+------------------+----------------------+--------------------------+
{};
the control flow:
Root root;
root.start();
root.process_event(init());
root.process_event(sub());
root.process_event(process());
output log:
=============> start
Root_::InitEvent: Enter to Root_ state.
Root_::InitEvent: Enter to Root_::Empty state.
=============> init
Exit from Root_::Empty state.
init: Enter to Root_::Initial state.
=============> sub
Exit from Root_::Initial state.
sub: Enter to Root_::SubFsm_ state.
sub: Enter to SubFsm_::Empty state.
sub: Enter to SubFsm_::AllOk state.
Exit from SubFsm_::Empty state.
front::none: Enter to SubFsm_::Waiting state.
=============> process
Exit from SubFsm_::Waiting state.
SubFsm_::A_Exception()
State machine produces an exception on event process
Current state: SubFsm_::Waiting
Message: A_Process exception
Exit from SubFsm_::AllOk state.
error: Enter to SubFsm_::Error state.
No transition from state Root_::SubFsm_ on event process
Exit from SubFsm_::Waiting state.
Exit from SubFsm_::Error state.
Exit from Root_::SubFsm_ state.
error: Enter to Root_::Error state.
A I understood, after exception comes, the "process" event now in kind
of "unhandled" state. So it rises up to the root fsm that doesn't have
any suitable transition
How to make the root or sub to "forget" about unhandled event?