Как предотвратить прерывание boost :: statetechart из-за сгенерированного исключения

Я реализовал конечный автомат, который наследует boost :: statechart. Когда я звоню fsm.process_event( some_event() ) какая реакция выдает исключение, получается, что после того, как я обработаю исключение с помощью блока try-catch, мой экземпляр statemachine 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

0

Решение

Вы должны предоставить пользовательский обработчик исключений для вашего конечного автомата. Смотрите документацию по бусту здесь: http://www.boost.org/doc/libs/1_55_0/libs/statechart/doc/tutorial.html#ExceptionHandling

Для конечного автомата невозможно узнать, находится ли он все еще в действительном состоянии, когда генерируется исключение, поэтому действие по умолчанию для дескриптора исключения — завершить sm. Ваш пользовательский обработчик может выполнить очистку / проверку, чтобы убедиться, что sm находится в действительном состоянии, и распространять информацию вверх в другом поместье.

Лично я никогда не видел веских причин распространять информацию из СМ в порядке исключения. Это может быть, по всей вероятности, потому, что я никогда не работал в вашей конкретной области, но тем не менее здесь мой разум:

Если событие не имеет значения, тогда проигнорируйте его или зарегистрируйте его, это же событие может иметь значение в другом состоянии, но не в текущем. Если событие недействительно, то есть никогда не может произойти или имеет неправильное состояние, то это либо:

  • проблема с вашим кодом, и вы должны немедленно решить и устранить проблему
  • проблема с неправильным вводом из-за пределов модуля, содержащего SM (аппаратное обеспечение отправило 3 отключенных события подряд, этого никогда не может быть и т. д.). В этом случае вы не можете должным образом обработать исключение в локальном модуле, и лучше всего зарегистрировать проблему и переключиться на CatastrophicErrorState или что-то, что может быть оставлено только с EvReset или чем-то еще.
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]