Увеличить диаграмму состояний — передать данные о событиях в конструктор состояний с помощью triggering_event

Я хотел бы иметь возможность передавать данные из события в состояние, которое создается в результате перехода.

От этот пост в 2009 году и этот один в 2010 году использование triggering_event() предлагается. Однако я нигде не могу найти пример, который демонстрирует, как его использовать.

Кто-нибудь может помочь?

0

Решение

Следующий пример является реализацией диаграммы состояний Boost на основе описанного конечного автомата двигателя Вот. Вместо того чтобы использовать custom_reaction для извлечения скорости из события EvSetSpeed ​​(как в других состояниях здесь), я изменил его, чтобы вызвать triggering_event () в конструкторе состояния Start.

Что следует отметить:

  1. Старая документация для диаграммы состояний наддува Вот гласит: «вызывающий для triggering_event должен выполнить проверку типа или привести возвращаемое значение», так как triggering_event возвращает указатель на const event_base.
  2. Вызов triggering_event во время построения требует, чтобы вызывающее состояние происходило из состояния, а не simple_state. Это связано с тем, что triggering_event обращается к конечному автомату из конструктора. Для чего это стоит, я также отметил, что в документации говорится, что использование triggering_event часто подразумевает проблему с дизайном конечного автомата и его следует избегать.
  3. Возможно, кто-то, более знакомый с диаграммой состояний наддува, может прокомментировать это, но я обнаружил, что мне нужно было повторно опубликовать инициирующее событие в конструкторе состояния Start, если я хотел, чтобы он перешел в состояние Running (как указано в моем списке реакций).

Наконец, стоит отметить, что попытка вызвать triggering_event в конструкторе начального состояния конечного автомата приведет к нулевому возвращаемому значению. Это связано с тем, что начальное состояние создается во время вызова для инициирования, где нет инициирующего события.

#include <boost/statechart/state_machine.hpp>
#include <boost/statechart/simple_state.hpp>
#include <boost/statechart/state.hpp>
#include <boost/statechart/event.hpp>
#include <boost/statechart/in_state_reaction.hpp>
#include <boost/statechart/transition.hpp>
#include <boost/mpl/list.hpp>
#include <boost/statechart/custom_reaction.hpp>
#include <iostream>

namespace mpl = boost::mpl;
namespace sc = boost::statechart;

class EvHalt : public sc::event< EvHalt > {};
class EvSetSpeed : public sc::event< EvSetSpeed >
{
public:
EvSetSpeed(int speed) : _speed(speed) {}
int getSpeed() const { return _speed; };

private:
int _speed;
};

class Idle;
class Start;
class Stop;
class Running;

class Motor : public sc::state_machine<Motor, Idle> {};

class Idle : public sc::simple_state<Idle, Motor>
{
public:
typedef mpl::list<
sc::transition< EvSetSpeed, Start >,
sc::transition< EvHalt, Idle > > reactions;

Idle() { std::cout << "Entering Idle State" << std::endl; };
~Idle() { std::cout << "Exiting Idle State" << std::endl; };
};

class Start : public sc::state<Start, Motor>
{
public:
typedef mpl::list<
sc::transition< EvSetSpeed, Running >,
sc::transition< EvHalt, Stop  > > reactions;

Start(my_context ctx) : _speed(0), my_base(ctx)
{
auto trigEvt = dynamic_cast<const EvSetSpeed*>(triggering_event());
if (trigEvt) // returns true if trigEvt is indeed an EvSetSpeed event
{
_speed = trigEvt->getSpeed();
post_event(*trigEvt);
std::cout << "Entering Start State at speed " << _speed << std::endl;
}
else
std::cout << "Entering Start State. Triggering Event is NOT EvSetSpeed." << std::endl;
};
~Start() { std::cout << "Exiting Start State" << std::endl; };
private:
int _speed;  // Unused in this example.
};

class Running : public sc::simple_state<Running, Motor>
{
public:
typedef mpl::list<
sc::custom_reaction< EvSetSpeed >,
sc::custom_reaction< EvHalt  > > reactions;

sc::result react(const EvSetSpeed& ev)
{
std::cout << "In Running Mode: Set Speed to " << ev.getSpeed() << std::endl;
return discard_event();
}
sc::result react(const EvHalt& ev)
{
std::cout << "In Running Mode: Halting Motor" << std::endl;
post_event(ev);
return transit<Stop>();
}

Running() { std::cout << "Entering Running State" << std::endl; };
~Running() { std::cout << "Exiting Running State" << std::endl; };
};

class Stop : public sc::simple_state<Stop, Motor>
{
public:
typedef sc::transition< EvHalt, Idle > reactions;

Stop() { std::cout << "Entering Stop State" << std::endl; };
~Stop() { std::cout << "Exiting Stop State" << std::endl; };
};

int main()
{
Motor myMotor;
myMotor.initiate();
myMotor.process_event(EvSetSpeed(100));
myMotor.process_event(EvSetSpeed(200));
myMotor.process_event(EvHalt());
myMotor.process_event(EvSetSpeed(300));
myMotor.process_event(EvHalt());
myMotor.process_event(EvHalt());
return 0;
}
0

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

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