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:
fig5.png
It can be converted to the diagram below.
fig6.png
#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:
fig7.png
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 >
        > {};

Add a New Comment