BOOST :: MSM Проверка переходов между состояниями в состоянии охраны

У меня есть общее условие охраны, которое я хотел бы условно предотвратить при определенных обстоятельствах. Ниже приведен несколько C ++ / псевдокод того, что я хотел бы сделать.

bool operator()(Event const& evt, FSM & fsm, SourceState& src, TargetState& tgt )
{
bool transition = (current_state != next_state);
bool transitionAllowed = (x | y | z); //some custom condition
return (transition && transitionAllowed);
}

Я хотел бы знать, отличается ли целевое состояние от исходного состояния и на основании этого определить, можем ли мы разрешить переходы на основе других параметров. До сих пор я не нашел большого успеха с документацией.

0

Решение

Кажется, ваш вопрос состоит из двух частей.
Один из них — как проверить текущее состояние и следующее состояние. Другой способ проверить пользовательские условия.

Для проверки текущего состояния и следующего состояния вы можете использовать std::is_same мета-функция.

Вот пример охранника:

struct Guard1 {
template <class Event, class Fsm, class Source, class Target>
bool operator()(Event const&, Fsm& fsm, Source& src, Target&) const {
bool transition = !std::is_same<Source, Target>::value;
bool transitionAllowed = x() || fsm.y || src.z;
return transition && transitionAllowed;
}
};

Вот таблица переходов:

// Transition table
struct transition_table:mpl::vector<
//          Start   Event   Next    Action      Guard
//          source and target is the same
msmf::Row < State1, Event1, State1, msmf::none, Guard1 >,

//          source and target is different
msmf::Row < State1, Event2, State2, msmf::none, Guard1 >
> {};

Переход, вызванный Event1, имеет одинаковые исходное и целевое состояния. Оба являются State1. Переход, вызванный Event2, имеет разные исходное и целевое состояния. Исходное состояние — State1, а целевое состояние — State2.

Бывший случай std::is_same<Source, Target>::value возвращает истину, а последний случай возвращает ложь.
Переменная transition является нагией результата.

Вы можете использовать это как часть возвращаемого значения.

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

  • x() это глобальная функция. Конечно, вы можете использовать глобальные переменные, как это.
  • y является переменной-членом конечного автомата.
  • z переменная-член исходного состояния State1.

Вот полный код:

#include <iostream>
#include <boost/msm/back/state_machine.hpp>

#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#include <boost/static_assert.hpp>

namespace msm = boost::msm;
namespace msmf = boost::msm::front;
namespace mpl = boost::mpl;

// You can test changing the value
bool const example_value = true;

struct Event1 {};
struct Event2 {};

// example of a condition
bool x() { return example_value; }

struct Sm_:msmf::state_machine_def<Sm_>
{
// States
struct State1:msmf::state<> {
template <class Event,class Fsm>
void on_entry(Event const&, Fsm&) const {
std::cout << "State1::on_entry()" << std::endl;
}
template <class Event,class Fsm>
void on_exit(Event const&, Fsm&) const {
std::cout << "State1::on_exit()" << std::endl;
}
bool z = example_value; // example of a condition
};
struct State2:msmf::state<> {
template <class Event,class Fsm>
void on_entry(Event const&, Fsm&) {
std::cout << "State2::on_entry()" << std::endl;
}
template <class Event,class Fsm>
void on_exit(Event const&, Fsm&) const {
std::cout << "State2::on_exit()" << std::endl;
}
int property;
};
// Set initial state
typedef State1 initial_state;

// Guards
struct Guard1 {
template <class Event, class Fsm, class Source, class Target>
bool operator()(Event const&, Fsm& fsm, Source& src, Target&) const {
bool transition = !std::is_same<Source, Target>::value;
bool transitionAllowed = x() || fsm.y || src.z;
return transition && transitionAllowed;
}
};

// Transition table
struct transition_table:mpl::vector<
//          Start   Event   Next    Action      Guard
//          source and target is the same
msmf::Row < State1, Event1, State1, msmf::none, Guard1 >,

//          source and target is different
msmf::Row < State1, Event2, State2, msmf::none, Guard1 >
> {};
bool y = example_value; // example of a condition
};

// Pick a back-end
typedef msm::back::state_machine<Sm_> Sm;

int main() {
Sm sm;
sm.start();

std::cout << "> Send Event1()" << std::endl;
sm.process_event(Event1());

std::cout << "> Send Event2()" << std::endl;
sm.process_event(Event2());
}

Вы можете изменить значения пользовательских условий.

// You can test changing the value
bool const example_value = true;

Если для параметра example_value задано значение false, пользовательское условие не выполняется.

Если пользовательское условие НЕ выполняется, оба Event1 а также Event2 не делайте переход.
Если пользовательские условия удовлетворены, Event1 не выполняет переход, потому что исходное и целевое состояния совпадают. Event2 делает переход.

Вот бегущая демка.

Дело example_value = true

https://wandbox.org/permlink/6qHcW9e6JX4QXAuH

Дело example_value = false

https://wandbox.org/permlink/HxaGpAr90YLEc5l8

1

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

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