Using boost::msm inside FairMQStateMachine.

This commit is contained in:
Thorsten Kollegger 2014-04-26 10:11:39 +00:00 committed by Florian Uhlig
parent adc7443aa5
commit 24d26e802a
2 changed files with 236 additions and 171 deletions

View File

@ -5,166 +5,43 @@
* @author D. Klein, A. Rybalchenko * @author D. Klein, A. Rybalchenko
*/ */
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include "FairMQStateMachine.h" #include "FairMQStateMachine.h"
#include "FairMQLogger.h" #include "FairMQLogger.h"
FairMQStateMachine::FairMQStateMachine()
FairMQStateMachine::FairMQStateMachine() :
fState(IDLE)
{
}
void FairMQStateMachine::ChangeState(int event)
{
switch(fState) {
case IDLE:
switch(event) {
case INIT:
LOG(STATE) << "IDLE --init--> INITIALIZING";
fState = INITIALIZING;
Init();
return;
case END:
LOG(STATE) << "IDLE --end--> (o)";
return;
default:
return;
}
break;
case INITIALIZING:
switch(event) {
case SETOUTPUT:
LOG(STATE) << "INITIALIZING --bind--> SETTINGOUTPUT";
fState = SETTINGOUTPUT;
InitOutput();
return;
default:
return;
}
break;
case SETTINGOUTPUT:
switch(event) {
case SETINPUT:
LOG(STATE) << "SETTINGOUTPUT --connect--> SETTINGINPUT";
fState = SETTINGINPUT;
InitInput();
return;
default:
return;
}
break;
case SETTINGINPUT:
switch(event) {
case PAUSE:
LOG(STATE) << "SETTINGINPUT --pause--> WAITING";
fState = WAITING;
Pause();
return;
case RUN:
LOG(STATE) << "SETTINGINPUT --run--> RUNNING";
fState = RUNNING;
running_state = boost::thread(boost::bind(&FairMQStateMachine::Run, this));
return;
default:
return;
}
break;
case WAITING:
switch(event) {
case RUN:
LOG(STATE) << "WAITING --run--> RUNNING";
fState = RUNNING;
running_state = boost::thread(boost::bind(&FairMQStateMachine::Run, this));
return;
case STOP:
LOG(STATE) << "WAITING --stop--> IDLE";
fState = IDLE;
Shutdown();
return;
default:
return;
}
break;
case RUNNING:
switch(event) {
case PAUSE:
LOG(STATE) << "RUNNING --pause--> WAITING";
fState = WAITING;
running_state.join();
return;
case STOP:
LOG(STATE) << "RUNNING --stop--> IDLE";
fState = IDLE;
running_state.join();
Shutdown();
return;
default:
return;
}
break;
default:
break;
}//switch fState
}
void FairMQStateMachine::Init()
{
}
void FairMQStateMachine::Run()
{
}
void FairMQStateMachine::Pause()
{
}
void FairMQStateMachine::Shutdown()
{
}
void FairMQStateMachine::InitOutput()
{
}
void FairMQStateMachine::InitInput()
{ {
start();
} }
FairMQStateMachine::~FairMQStateMachine() FairMQStateMachine::~FairMQStateMachine()
{ {
stop();
} }
void FairMQStateMachine::ChangeState(int event)
{
switch (event)
{
case INIT:
process_event(FairMQFSM::INIT());
return;
case SETOUTPUT:
process_event(FairMQFSM::SETOUTPUT());
return;
case SETINPUT:
process_event(FairMQFSM::SETINPUT());
return;
case RUN:
process_event(FairMQFSM::RUN());
return;
case PAUSE:
process_event(FairMQFSM::PAUSE());
return;
case STOP:
process_event(FairMQFSM::STOP());
return;
case END:
process_event(FairMQFSM::END());
return;
}
}

View File

@ -9,31 +9,219 @@
#define FAIRMQSTATEMACHINE_H_ #define FAIRMQSTATEMACHINE_H_
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
#include <boost/msm/front/euml/common.hpp>
#include <boost/msm/front/euml/operator.hpp>
#include <boost/function.hpp>
#include "FairMQLogger.h"
class FairMQStateMachine namespace msm = boost::msm;
namespace mpl = boost::mpl;
namespace msmf = boost::msm::front;
namespace FairMQFSM
{
// defining events for the boost MSM state machine
struct INIT
{
};
struct SETOUTPUT
{
};
struct SETINPUT
{
};
struct PAUSE
{
};
struct RUN
{
};
struct STOP
{
};
struct END
{
};
// defining the boost MSM state machine
struct FairMQFSM_ : public msm::front::state_machine_def<FairMQFSM_>
{
template <class Event, class FSM>
void on_entry(Event const&, FSM&)
{
LOG(STATE) << "Entering FairMQ state machine";
fState = IDLE;
}
template <class Event, class FSM>
void on_exit(Event const&, FSM&)
{
LOG(STATE) << "Exiting FairMQ state machine";
}
// The list of FSM states
struct IDLE_FSM : public msm::front::state<>
{
};
struct INITIALIZING_FSM : public msm::front::state<>
{
};
struct SETTINGOUTPUT_FSM : public msm::front::state<>
{
};
struct SETTINGINPUT_FSM : public msm::front::state<>
{
};
struct WAITING_FSM : public msm::front::state<>
{
};
struct RUNNING_FSM : public msm::front::state<>
{
};
// Define initial state
typedef IDLE_FSM initial_state;
// Actions
struct TestFct
{
template <class EVT, class FSM, class SourceState, class TargetState>
void operator()(EVT const&, FSM&, SourceState&, TargetState&)
{
LOG(STATE) << "Transition from " << typeid(SourceState).name() << " to " << typeid(TargetState).name() << " with event:" << typeid(EVT).name();
}
};
struct InitFct
{
template <class EVT, class FSM, class SourceState, class TargetState>
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
{
fsm.fState = INITIALIZING;
fsm.Init();
}
};
struct SetOutputFct
{
template <class EVT, class FSM, class SourceState, class TargetState>
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
{
fsm.fState = SETTINGOUTPUT;
fsm.InitOutput();
}
};
struct SetInputFct
{
template <class EVT, class FSM, class SourceState, class TargetState>
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
{
fsm.fState = SETTINGINPUT;
fsm.InitInput();
}
};
struct RunFct
{
template <class EVT, class FSM, class SourceState, class TargetState>
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
{
fsm.fState = RUNNING;
fsm.running_state = boost::thread(boost::bind(&FairMQFSM_::Run, &fsm));
}
};
struct StopFct
{
template <class EVT, class FSM, class SourceState, class TargetState>
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
{
fsm.fState = IDLE;
fsm.running_state.join();
fsm.Shutdown();
}
};
struct PauseFct
{
template <class EVT, class FSM, class SourceState, class TargetState>
void operator()(EVT const&, FSM& fsm, SourceState&, TargetState&)
{
fsm.fState = WAITING;
fsm.running_state.join();
fsm.Pause();
}
};
// actions to be overwritten by derived classes
virtual void Init()
{
}
virtual void Run()
{
}
virtual void Pause()
{
}
virtual void Shutdown()
{
}
virtual void InitOutput()
{
}
virtual void InitInput()
{
}
// Transition table for FairMQFMS
struct transition_table : mpl::vector<
// Start Event Next Action Guard
// +---------+---------+-------+---------+--------+
msmf::Row<IDLE_FSM, INIT, INITIALIZING_FSM, InitFct, msmf::none>,
msmf::Row<IDLE_FSM, END, msmf::none, TestFct, msmf::none>, // this is an invalid transition...
msmf::Row<INITIALIZING_FSM, SETOUTPUT, SETTINGOUTPUT_FSM, SetOutputFct, msmf::none>,
msmf::Row<SETTINGOUTPUT_FSM, SETINPUT, SETTINGINPUT_FSM, SetInputFct, msmf::none>,
msmf::Row<SETTINGINPUT_FSM, PAUSE, WAITING_FSM, PauseFct, msmf::none>,
msmf::Row<SETTINGINPUT_FSM, RUN, RUNNING_FSM, RunFct, msmf::none>,
msmf::Row<WAITING_FSM, RUN, RUNNING_FSM, RunFct, msmf::none>,
msmf::Row<WAITING_FSM, STOP, IDLE_FSM, StopFct, msmf::none>,
msmf::Row<RUNNING_FSM, PAUSE, WAITING_FSM, PauseFct, msmf::none>,
msmf::Row<RUNNING_FSM, STOP, IDLE_FSM, StopFct, msmf::none> >
{
};
// Replaces the default no-transition response.
template <class FSM, class Event>
void no_transition(Event const& e, FSM&, int state)
{
LOG(STATE) << "no transition from state " << state << " on event " << typeid(e).name() << std::endl;
}
// this is to run certain functions (e.g. Run()) as separate task
boost::thread running_state;
// backward compatibility to FairMQStateMachine
enum State
{
IDLE,
INITIALIZING,
SETTINGOUTPUT,
SETTINGINPUT,
WAITING,
RUNNING
};
State fState;
};
typedef msm::back::state_machine<FairMQFSM_> FairMQFSM;
}
class FairMQStateMachine : public FairMQFSM::FairMQFSM
{ {
public: public:
enum State { enum Event
IDLE, INITIALIZING, SETTINGOUTPUT, SETTINGINPUT, WAITING, RUNNING {
}; INIT,
enum Event { SETOUTPUT,
INIT, SETOUTPUT, SETINPUT, PAUSE, RUN, STOP, END SETINPUT,
PAUSE,
RUN,
STOP,
END
}; };
FairMQStateMachine(); FairMQStateMachine();
void ChangeState(int event);
virtual ~FairMQStateMachine(); virtual ~FairMQStateMachine();
void ChangeState(int event);
protected:
State fState;
Event fEvent;
virtual void Init();
virtual void Run();
virtual void Pause();
virtual void Shutdown();
virtual void InitOutput();
virtual void InitInput();
boost::thread running_state;
}; };
#endif /* FAIRMQSTATEMACHINE_H_ */ #endif /* FAIRMQSTATEMACHINE_H_ */