Junction Pseudo State
Boost.Msm doesn't support junction pseudo states directly. If you want to implement the junction pseudo states, you have to convert your UML model. The converting process is very simple. Separate each individual transition from the transitions that relate to the junction pseudo state.
For example, Consider the following diagram:
It can be converted to the diagram below.
#include <iostream> #include <boost/msm/back/state_machine.hpp> #include <boost/msm/front/state_machine_def.hpp> #include <boost/msm/front/functor_row.hpp> namespace { namespace msm = boost::msm; namespace msmf = boost::msm::front; namespace mpl = boost::mpl; // Events struct Event1 { Event1(int val):val(val) {} int val; }; // ----- State machine struct Sm1_:msmf::state_machine_def<Sm1_> { struct State1_:msmf::state_machine_def<State1_>{}; // Set initial state typedef State1_ initial_state; // Guards struct Guard1 { template <class Event, class Fsm, class SourceState, class TargetState> bool operator()(Event const& e, Fsm&, SourceState&, TargetState&) const { if (e.val == 1) return true; return false; } }; struct Guard2 { template <class Event, class Fsm, class SourceState, class TargetState> bool operator()(Event const& e, Fsm&, SourceState&, TargetState&) const { if (e.val == 2) return true; return false; } }; // Actions struct Action1 { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const&, Fsm&, SourceState&, TargetState&) const { std::cout << "Action1" << std::endl; } }; struct Action2 { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const&, Fsm&, SourceState&, TargetState&) const { std::cout << "Action2" << std::endl; } }; // Transition table struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < State1_, Event1, State1_, Action1, Guard1 >, msmf::Row < State1_, Event1, State1_, Action2, Guard2 > > {}; }; // back-end typedef msm::back::state_machine<Sm1_> Sm1; void test() { Sm1 sm1; sm1.start(); std::cout << "> Send Event1(1)" << std::endl; sm1.process_event(Event1(1)); std::cout << "> Send Event1(2)" << std::endl; sm1.process_event(Event1(2)); } } int main() { test(); return 0; } // Output: // // > Send Event1(1) // Action1 // > Send Event1(2) // Action2
If/else branch
Sometimes you might want to use if/else branches. Consider the following diagram:
Boost.Msm doesn't support if/else branches directly. As I mentioned earlier on, transition tables and internal transition tables are evaluated from the bottom row to the top row. This means you can implement if/else branches as placing the else row to the top position in the rows that make up the branch group. The guard in the else row is none. See the following transition table:
// Transition table struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < State1_, Event1, State1_, Action2, msmf::none >, // else msmf::Row < State1_, Event1, State1_, Action1, Guard1 > > {};
page revision: 19, last edited: 05 Jun 2012 07:48