Skip to content

Instantly share code, notes, and snippets.

@ahamez
Created January 7, 2016 16:46
Show Gist options
  • Select an option

  • Save ahamez/4c2d1c283094976c5889 to your computer and use it in GitHub Desktop.

Select an option

Save ahamez/4c2d1c283094976c5889 to your computer and use it in GitHub Desktop.
Some Boost.MSM usages
#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 msm = boost::msm;
namespace mpl = boost::mpl;
using namespace msm::front;
struct Visitor
{
std::vector<std::string> names;
template <typename T>
void
visit_state(const T&)
{
names.emplace_back(T::name());
}
};
struct VisitableState
{
using accept_sig = msm::back::args<void, Visitor&>;
virtual ~VisitableState()
{}
void
accept(Visitor&)
const
{}
};
struct SubEvt0{};
struct SubEvt1{};
struct SubState0
: public msm::front::state<VisitableState>
{
template <typename Event, typename SM>
void
on_entry(const Event&, const SM&)
{
std::cout << "Entering SubState0\n";
}
template <typename Event, typename SM>
void
on_exit(const Event&, const SM&)
{
std::cout << "Exiting SubState0\n";
}
void
accept(Visitor& v)
const
{
v.visit_state(*this);
}
static
std::string
name()
{
return "SubState0";
}
};
struct SubState1
: public msm::front::state<VisitableState>
{
void
accept(Visitor& v)
const
{
v.visit_state(*this);
}
static
std::string
name()
{
return "SubState1";
}
};
struct SubStateMachine_
: public msm::front::state_machine_def<SubStateMachine_, VisitableState>
{
using initial_state = SubState0;
struct transition_table
: boost::mpl::vector<
Row < SubState0
, SubEvt0
, SubState1
, none
, none
>
, Row < SubState1
, SubEvt1
, SubState0
, none
, none
>
>
{};
template <class FSM,class Event>
void no_transition(Event const& e, FSM&,int state)
{
std::cout << "no transition from sub state " << state
<< " on event " << typeid(e).name() << std::endl;
}
};
using SubStateMachine = msm::back::state_machine<SubStateMachine_>;
struct Evt0{};
struct Evt1{};
struct EvtError{};
struct EvtRecoverableError{};
struct EvtRecoverError{};
struct EvtInternalError{};
struct S0_
: msm::front::state_machine_def<S0_, VisitableState>
{
struct SubState_
: SubStateMachine
{};
using initial_state = SubState_ ;
void
accept(Visitor& v)
const
{
v.visit_state(*this);
}
static
std::string
name()
{
return "S0";
}
};
using S0 = msm::back::state_machine<S0_>;
struct S1
: public msm::front::state<VisitableState>
{
using deferred_events = mpl::vector<Evt0>;
void
accept(Visitor& v)
const
{
v.visit_state(*this);
}
static
std::string
name()
{
return "S1";
}
};
struct OK
: public msm::front::state<VisitableState>
{
void
accept(Visitor& v)
const
{
v.visit_state(*this);
}
static
std::string
name()
{
return "OK";
}
};
struct Error
: public msm::front::terminate_state<VisitableState>
{
void
accept(Visitor& v)
const
{
v.visit_state(*this);
}
static
std::string
name()
{
return "Error";
}
};
struct RecoverableError
: public msm::front::interrupt_state<EvtRecoverError, VisitableState>
{
void
accept(Visitor& v)
const
{
v.visit_state(*this);
}
static
std::string
name()
{
return "RecoverableError";
}
};
struct StateMachine_
: public msm::front::state_machine_def<StateMachine_, VisitableState>
{
using initial_state = mpl::vector<S0, OK>;
struct transition_table
: boost::mpl::vector<
Row < S0
, Evt0
, S1
, none
, none
>
, Row < S1
, Evt1
, S0
, none
, none
>
, Row < OK
, EvtError
, Error
, none
, none
>
, Row < OK
, EvtRecoverableError
, RecoverableError
, none
, none
>
, Row < RecoverableError
, EvtRecoverError
, OK
, none
, none
>
>
{};
template <class FSM,class Event>
void no_transition(Event const& e, FSM&,int state)
{
std::cout << "no transition from state " << state
<< " on event " << typeid(e).name() << std::endl;
}
};
using StateMachine = msm::back::state_machine<StateMachine_>;
void
pstate(StateMachine& sm)
{
std::cout << "Active states:\n";
auto v = Visitor{};
sm.visit_current_states(boost::ref(v));
for (const auto& name : v.names)
{
std::cout << " - " << name << '\n';
}
}
int
main()
{
std::cout << "A\n";
auto sm = StateMachine{};
sm.start();
pstate(sm);
std::cout << "A.1\n";
sm.process_event(SubEvt0{});
pstate(sm);
std::cout << "A.2\n";
sm.process_event(SubEvt1{});
pstate(sm);
std::cout << "B\n";
sm.process_event(Evt0{});
pstate(sm);
std::cout << "C\n";
sm.process_event(Evt1{});
pstate(sm);
std::cout << "D\n";
sm.process_event(EvtRecoverableError{});
pstate(sm);
std::cout << "E\n";
sm.process_event(Evt0{});
pstate(sm);
std::cout << "F\n";
sm.process_event(EvtRecoverError{});
pstate(sm);
std::cout << "G\n";
sm.process_event(EvtError{});
pstate(sm);
std::cout << "H\n";
sm.process_event(Evt0{});
pstate(sm);
std::cout << "I\n";
sm.process_event(EvtRecoverError{});
pstate(sm);
std::cout << "J\n";
sm.start();
sm.process_event(Evt0{});
pstate(sm);
std::cout << "K\n";
sm.process_event(Evt0{});
sm.process_event(Evt0{});
pstate(sm);
std::cout << "L\n";
sm.process_event(Evt1{});
pstate(sm);
std::cout << "M\n";
sm.process_event(Evt1{});
pstate(sm);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment