Я реализовал машину состояний, которая наследует boost :: statechart. Когда я вызываю fsm.process_event( some_event() )
какая реакция, как ожидается, fsm.process_event( some_event() )
исключение, оказывается, что после обработки исключения с блоком try-catch мой экземпляр fsm
завершается. То есть fsm.terminated()
возвращает true
. В некоторых случаях я не хочу, чтобы это прекращалось. Например, когда я хочу, чтобы fsm.process_event( irrelevant_event() )
исключение, чтобы сообщить вызывающему пользователю 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
Вы должны предоставить собственный обработчик исключений на свой конечный автомат. См. Документацию по ускорению: http://www.boost.org/doc/libs/1_55_0/libs/statechart/doc/tutorial.html#ExceptionHandling
Невозможно, чтобы конечный автомат знал, находится ли он в правильном состоянии, когда возникает исключение, поэтому действие дескриптора исключения по умолчанию заключается в завершении sm. Ваш пользовательский обработчик может выполнить очистку/проверку, чтобы убедиться, что sm находится в правильном состоянии и распространяет информацию вверх в другой усадьбе.
Лично я никогда не видел веских оснований распространять информацию из SM за исключением. Вероятно, это возможно потому, что я никогда не работал в вашем конкретном домене, но тем не менее здесь я был рациональным:
Если событие не имеет значения, то проигнорируйте его или запишите его, это же событие может иметь значение в другом состоянии, а не в текущем. Если событие недействительно, т.е. Никогда не может произойти или имеет неправильное состояние, то это либо: