#include <iostream>
#define PRINT(X) std::cout<<X<<std::endl
typedef unsigned char uint8_t;
template<typename ConcreteMachineType>
struct FiniteStateMachine
{
typedef ConcreteMachineType ConcreteMachine_t;
typedef typename ConcreteMachineType::StateType State_t;
typedef typename ConcreteMachineType::StateFunctionType StateFunction_t;
typedef typename ConcreteMachineType::StatesTableType StateTable_t;
typedef typename ConcreteMachineType::TransitionFunctionType TransitionFunction_t;
typedef typename ConcreteMachineType::TransitionsTableType TransitionTable_t;
ConcreteMachineType _myObject;
State_t _currentState;
static const StateTable_t &_crStatesTable;
static const TransitionTable_t &_crTransitionsTable;
uint8_t isGood() const
{
PRINT("isGood");
return _currentState!=ConcreteMachineType::STATE_BAD;
}
State_t DispatchCurrentState()
{
PRINT("DispatchCurrentState");
const StateFunction_t pFunctionStateExec(_crStatesTable[_currentState]);
const State_t eNewState(pFunctionStateExec?pFunctionStateExec(&_myObject):ConcreteMachineType::STATE_BAD);
TransitionFunction_t pFunctionTransition = _crTransitionsTable[_currentState][eNewState];
_currentState=eNewState;
if(pFunctionTransition) pFunctionTransition(&_myObject);
return eNewState;
}
static const StateTable_t &initStates()
{
PRINT("initStates");
static StateTable_t x = {};
for(uint8_t i=0;i!=ConcreteMachineType::STATES_SIZE;++i) x[i]=NULL;
ConcreteMachineType::completeInitStates(x);
return x;
}
static const TransitionTable_t &initTransitions()
{
PRINT("initTransitions");
static TransitionTable_t x = {};
for(uint8_t i=0;i!=ConcreteMachineType::STATES_SIZE;++i)
for(uint8_t j=0;j!=ConcreteMachineType::STATES_SIZE;++j)
x[i][j]=NULL;
ConcreteMachineType::completeInitTransitions(x);
return x;
}
FiniteStateMachine()
:_currentState(State_t(0))
{
PRINT("FiniteStateMachine");
}
~FiniteStateMachine()
{
PRINT("~FiniteStateMachine");
}
};//FiniteStateMachine
template<typename ConcreteMachineType>
const typename FiniteStateMachine<ConcreteMachineType>::StateTable_t &FiniteStateMachine<ConcreteMachineType>::_crStatesTable=FiniteStateMachine<ConcreteMachineType>::initStates();
template<typename ConcreteMachineType>
const typename FiniteStateMachine<ConcreteMachineType>::TransitionTable_t &FiniteStateMachine<ConcreteMachineType>::_crTransitionsTable=FiniteStateMachine<ConcreteMachineType>::initTransitions();
struct DummyMachineClass
{
enum State_e
{
eState_Init
,eState_Foo
,eState_Bar
,STATES_SIZE
,STATE_BAD
};
int iInitCount;
typedef State_e StateType;
//static const StateType StatesAmout_i=STATES_SIZE;
typedef StateType (*StateFunctionType)(void *instance);
static StateType init(void * instance){DummyMachineClass *me=static_cast<DummyMachineClass *>(instance);PRINT("init: "<<me->iInitCount); me->iInitCount++; return eState_Foo;}
static StateType foo (void * /*instance*/){PRINT("foo");return eState_Bar;}
static StateType bar (void * /*instance*/){PRINT("bar");return eState_Init;}
typedef uint8_t (*TransitionFunctionType)(void *instance);
static uint8_t init2foo(void * /*instance*/){PRINT("init2foo");return 0;}
static uint8_t foo2bar (void * /*instance*/){PRINT("foo2bar");return 0;}
static uint8_t foo2foo (void * /*instance*/){PRINT("foo2foo");return 0;}
static uint8_t bar2foo (void * /*instance*/){PRINT("bar2foo");return 0;}
static uint8_t bar2bar (void * /*instance*/){PRINT("bar2bar");return 0;}
static uint8_t bar2init(void * /*instance*/){PRINT("bar2init");return 0;}
typedef StateFunctionType StatesTableType[STATES_SIZE];
typedef TransitionFunctionType TransitionsTableType[STATES_SIZE][STATES_SIZE];
//private:
static void completeInitStates(StatesTableType &/*toInit*/);
static void completeInitTransitions(TransitionsTableType &/*toInit*/);
DummyMachineClass()
:iInitCount(0)
{
PRINT("DummyMachineClass");
}
~DummyMachineClass()
{
PRINT("~DummyMachineClass");
}
};//FSMDummyUser
void DummyMachineClass::completeInitStates(StatesTableType &toInit)
{
PRINT("completeInitStates");
toInit[eState_Init]=DummyMachineClass::init;
toInit[eState_Foo ]=DummyMachineClass::foo;
toInit[eState_Bar ]=DummyMachineClass::bar;
}
void DummyMachineClass::completeInitTransitions(TransitionsTableType &toInit)
{
PRINT("completeInitTransitions");
toInit[eState_Init][eState_Foo ]=init2foo;
toInit[eState_Foo ][eState_Foo ]=foo2foo;
toInit[eState_Foo ][eState_Bar ]=foo2bar;
toInit[eState_Bar ][eState_Foo ]=bar2foo;
toInit[eState_Bar ][eState_Bar ]=bar2bar;
toInit[eState_Bar ][eState_Init]=bar2init;
}
typedef FiniteStateMachine<DummyMachineClass> DummyFiniteStateMachine_t;
int main()
{
PRINT("main");
DummyFiniteStateMachine_t t;
int iTimesToRun=10;
while(t.isGood() && iTimesToRun-->0){t.DispatchCurrentState();}
return 0;
}