Using the following example as a template:
http://svn.boost.org/svn/boost/trunk/libs/msm/doc/HTML/examples/CompositeTutorialWithEumlTable.cppI am trying to create a state machine that consists of an alarm state and a composite state (submachine). When an alarm event is posted while in the composite state, the state machine is supposed to transition to the Alarm state; however, the machine complains that no transition from the composite state on the alarm event exists. This is similar to the example where the player is in playing and a stop event is received.
Below is a dumbed-down version of my state machine:
Here is the implementation:
// File: StateMachine.cpp
#include <iostream>
// back-end
#include <boost/msm/back/state_machine.hpp>
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/euml/euml.hpp>
namespace msm = boost::msm;
namespace mpl = boost::mpl;
using namespace std;
namespace
{
static bool s_deviceInited = false;
struct setDeviceInited {
template<class Fsm, class Evt, class SourceState, class TargetState>
void operator()(Evt const& evt, Fsm& fsm, SourceState& ss,
TargetState& ts) {
s_deviceInited = true;
std::cout << "s_deviceInited=" << s_deviceInited << std::endl;
}
};
struct resetDeviceInited {
template<class Fsm, class Evt, class SourceState, class TargetState>
void operator()(Evt const& evt, Fsm& fsm, SourceState& ss,
TargetState& ts) {
s_deviceInited = true;
std::cout << "s_deviceInited=" << s_deviceInited << std::endl;
}
};
struct deviceInited {
template<class Fsm, class Evt, class SourceState, class TargetState>
bool operator()(Evt const& evt, Fsm& fsm, SourceState& ss,
TargetState& ts) {
std::cout << "s_deviceInited=" << s_deviceInited << std::endl;
return s_deviceInited;
}
};
// events
struct EvDeviceInited : msm::front::euml::euml_event<EvDeviceInited>{};
struct EvAlarm : msm::front::euml::euml_event<EvAlarm>{};
struct EvAlarmCleared : msm::front::euml::euml_event<EvAlarmCleared>{};
// define some dummy instances for use in the transition table
EvDeviceInited evDeviceInited;
EvAlarm evAlarm;
EvAlarmCleared evAlarmCleared;
// The list of FSM states
struct Alarm_TImpl : public msm::front::state<> , public msm::front::euml::euml_state<Alarm_TImpl>
{
// every (optional) entry/exit methods get the event passed.
template <class Event,class FSM>
void on_entry(Event const&,FSM& ) {std::cout << "entering: Alarm" << std::endl;}
template <class Event,class FSM>
void on_exit(Event const&,FSM& ) {std::cout << "leaving: Alarm" << std::endl;}
};
struct Operate_TImpl : public msm::front::state<> , public msm::front::euml::euml_state<Operate_TImpl>
{
template <class Event,class FSM>
void on_entry(Event const& ,FSM&) {std::cout << "entering: Operate" << std::endl;}
template <class Event,class FSM>
void on_exit(Event const&,FSM& ) {std::cout << "leaving: Operate" << std::endl;}
};
struct Initialize_TImpl : public msm::front::state<> , public msm::front::euml::euml_state<Initialize_TImpl>
{
template <class Event,class FSM>
void on_entry(Event const& ,FSM&) {std::cout << "entering: Initialize" << std::endl;}
template <class Event,class FSM>
void on_exit(Event const&,FSM& ) {std::cout << "leaving: Initialize" << std::endl;}
};
Initialize_TImpl initialize;
Operate_TImpl operate;
// Normal Submachine front-end
struct Normal_T : public msm::front::state_machine_def<Normal_T>
{
template <class Event,class FSM>
void on_entry(Event const& ,FSM&) {std::cout << "entering: Normal" << std::endl;}
template <class Event,class FSM>
void on_exit(Event const&,FSM& ) {std::cout << "leaving: Normal" << std::endl;}
typedef Initialize_TImpl initial_state;
// Playing has a transition table
BOOST_MSM_EUML_DECLARE_TRANSITION_TABLE((
// +------------------------------------------------------------------------------+
operate == initialize [deviceInited()],
initialize == initialize + evDeviceInited / setDeviceInited()
// +------------------------------------------------------------------------------+
),transition_table )
};
// Normal Submachine back-end
typedef boost::msm::back::state_machine<Normal_T> Normal_THelper;
struct Normal_TImpl : public Normal_THelper,
public msm::front::euml::euml_state<Normal_THelper>
{
};
//to make the transition table more readable
Alarm_TImpl alarm;
Normal_TImpl normal;
// front-end: define the FSM structure
struct StateMachine_T : public msm::front::state_machine_def<StateMachine_T>
{
template <class Event,class FSM>
void on_entry(Event const& ,FSM&) {std::cout << "entering: StateMachine" << std::endl;}
template <class Event,class FSM>
void on_exit(Event const&,FSM& ) {std::cout << "leaving: StateMachine" << std::endl;}
// the initial state of the player SM. Must be defined
typedef Normal_TImpl initial_state;
BOOST_MSM_EUML_DECLARE_TRANSITION_TABLE((
normal + evAlarm / resetDeviceInited() == alarm,
alarm + evAlarmCleared == normal
),transition_table)
// Replaces the default no-transition response.
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;
}
};
// Link the back-end
typedef msm::back::state_machine<StateMachine_T> StateMachine;
void test()
{
StateMachine p;
p.start();
p.process_event(evAlarm);
p.process_event(evAlarmCleared);
p.process_event(evDeviceInited);
p.process_event(evAlarm);
p.process_event(evAlarmCleared);
p.process_event(evDeviceInited);
p.process_event(evAlarm);
p.process_event(evAlarmCleared);
p.process_event(evDeviceInited);
p.process_event(evAlarm);
p.process_event(evAlarmCleared);
p.stop();
}
}
int gpp_main()
{
test();
return 0;
}
Here is the output:
StateMachine entering: Normal entering: Initialize s_deviceInited=0 no transition from state 2 on event N12_GLOBAL__N_17EvAlarmE no transition from state 2 on event N12_GLOBAL__N_114EvAlarmClearedE leaving: Initialize s_deviceInited=1 entering: Initialize s_deviceInited=1 leaving: Initialize entering: Operate no transition from state 2 on event N12_GLOBAL__N_17EvAlarmE no transition from state 2 on event N12_GLOBAL__N_114EvAlarmClearedE no transition from state 2 on event N12_GLOBAL__N_114EvDeviceInitedE no transition from state 2 on event N12_GLOBAL__N_17EvAlarmE no transition from state 2 on event N12_GLOBAL__N_114EvAlarmClearedE no transition from state 2 on event N12_GLOBAL__N_114EvDeviceInitedE no transition from state 2 on event N12_GLOBAL__N_17EvAlarmE no transition from state 2 on event N12_GLOBAL__N_114EvAlarmClearedE leaving: Operate leaving: Normal leaving: StateMachine
See anything that could be causing my problem?