fork download
  1. #include <iostream>
  2. #define PRINT(X) std::cout<<X<<std::endl
  3.  
  4. typedef unsigned char uint8_t;
  5.  
  6. template<typename ConcreteMachineType>
  7. struct FiniteStateMachine
  8. {
  9. typedef ConcreteMachineType ConcreteMachine_t;
  10. typedef typename ConcreteMachineType::StateType State_t;
  11. typedef typename ConcreteMachineType::StateFunctionType StateFunction_t;
  12. typedef typename ConcreteMachineType::StatesTableType StateTable_t;
  13. typedef typename ConcreteMachineType::TransitionFunctionType TransitionFunction_t;
  14. typedef typename ConcreteMachineType::TransitionsTableType TransitionTable_t;
  15.  
  16. ConcreteMachineType _myObject;
  17. State_t _currentState;
  18. static const StateTable_t &_crStatesTable;
  19. static const TransitionTable_t &_crTransitionsTable;
  20.  
  21. uint8_t isGood() const
  22. {
  23. PRINT("isGood");
  24. return _currentState!=ConcreteMachineType::STATE_BAD;
  25. }
  26.  
  27. State_t DispatchCurrentState()
  28. {
  29. PRINT("DispatchCurrentState");
  30. const StateFunction_t pFunctionStateExec(_crStatesTable[_currentState]);
  31. const State_t eNewState(pFunctionStateExec?pFunctionStateExec(&_myObject):ConcreteMachineType::STATE_BAD);
  32. TransitionFunction_t pFunctionTransition = _crTransitionsTable[_currentState][eNewState];
  33. _currentState=eNewState;
  34. if(pFunctionTransition) pFunctionTransition(&_myObject);
  35. return eNewState;
  36. }
  37.  
  38. static const StateTable_t &initStates()
  39. {
  40. PRINT("initStates");
  41. static StateTable_t x = {};
  42.  
  43. for(uint8_t i=0;i!=ConcreteMachineType::STATES_SIZE;++i) x[i]=NULL;
  44.  
  45. ConcreteMachineType::completeInitStates(x);
  46. return x;
  47. }
  48.  
  49. static const TransitionTable_t &initTransitions()
  50. {
  51. PRINT("initTransitions");
  52. static TransitionTable_t x = {};
  53.  
  54. for(uint8_t i=0;i!=ConcreteMachineType::STATES_SIZE;++i)
  55. for(uint8_t j=0;j!=ConcreteMachineType::STATES_SIZE;++j)
  56. x[i][j]=NULL;
  57.  
  58. ConcreteMachineType::completeInitTransitions(x);
  59. return x;
  60. }
  61. FiniteStateMachine()
  62. :_currentState(State_t(0))
  63. {
  64. PRINT("FiniteStateMachine");
  65. }
  66. ~FiniteStateMachine()
  67. {
  68. PRINT("~FiniteStateMachine");
  69. }
  70. };//FiniteStateMachine
  71.  
  72. template<typename ConcreteMachineType>
  73. const typename FiniteStateMachine<ConcreteMachineType>::StateTable_t &FiniteStateMachine<ConcreteMachineType>::_crStatesTable=FiniteStateMachine<ConcreteMachineType>::initStates();
  74.  
  75. template<typename ConcreteMachineType>
  76. const typename FiniteStateMachine<ConcreteMachineType>::TransitionTable_t &FiniteStateMachine<ConcreteMachineType>::_crTransitionsTable=FiniteStateMachine<ConcreteMachineType>::initTransitions();
  77.  
  78. struct DummyMachineClass
  79. {
  80. enum State_e
  81. {
  82. eState_Init
  83. ,eState_Foo
  84. ,eState_Bar
  85. ,STATES_SIZE
  86. ,STATE_BAD
  87. };
  88.  
  89. int iInitCount;
  90. typedef State_e StateType;
  91. //static const StateType StatesAmout_i=STATES_SIZE;
  92. typedef StateType (*StateFunctionType)(void *instance);
  93.  
  94. static StateType init(void * instance){DummyMachineClass *me=static_cast<DummyMachineClass *>(instance);PRINT("init: "<<me->iInitCount); me->iInitCount++; return eState_Foo;}
  95. static StateType foo (void * /*instance*/){PRINT("foo");return eState_Bar;}
  96. static StateType bar (void * /*instance*/){PRINT("bar");return eState_Init;}
  97.  
  98. typedef uint8_t (*TransitionFunctionType)(void *instance);
  99.  
  100. static uint8_t init2foo(void * /*instance*/){PRINT("init2foo");return 0;}
  101. static uint8_t foo2bar (void * /*instance*/){PRINT("foo2bar");return 0;}
  102. static uint8_t foo2foo (void * /*instance*/){PRINT("foo2foo");return 0;}
  103. static uint8_t bar2foo (void * /*instance*/){PRINT("bar2foo");return 0;}
  104. static uint8_t bar2bar (void * /*instance*/){PRINT("bar2bar");return 0;}
  105. static uint8_t bar2init(void * /*instance*/){PRINT("bar2init");return 0;}
  106.  
  107. typedef StateFunctionType StatesTableType[STATES_SIZE];
  108. typedef TransitionFunctionType TransitionsTableType[STATES_SIZE][STATES_SIZE];
  109.  
  110. //private:
  111. static void completeInitStates(StatesTableType &/*toInit*/);
  112. static void completeInitTransitions(TransitionsTableType &/*toInit*/);
  113.  
  114. DummyMachineClass()
  115. :iInitCount(0)
  116. {
  117. PRINT("DummyMachineClass");
  118. }
  119. ~DummyMachineClass()
  120. {
  121. PRINT("~DummyMachineClass");
  122. }
  123. };//FSMDummyUser
  124.  
  125. void DummyMachineClass::completeInitStates(StatesTableType &toInit)
  126. {
  127. PRINT("completeInitStates");
  128. toInit[eState_Init]=DummyMachineClass::init;
  129. toInit[eState_Foo ]=DummyMachineClass::foo;
  130. toInit[eState_Bar ]=DummyMachineClass::bar;
  131. }
  132.  
  133. void DummyMachineClass::completeInitTransitions(TransitionsTableType &toInit)
  134. {
  135. PRINT("completeInitTransitions");
  136. toInit[eState_Init][eState_Foo ]=init2foo;
  137. toInit[eState_Foo ][eState_Foo ]=foo2foo;
  138. toInit[eState_Foo ][eState_Bar ]=foo2bar;
  139. toInit[eState_Bar ][eState_Foo ]=bar2foo;
  140. toInit[eState_Bar ][eState_Bar ]=bar2bar;
  141. toInit[eState_Bar ][eState_Init]=bar2init;
  142. }
  143.  
  144. typedef FiniteStateMachine<DummyMachineClass> DummyFiniteStateMachine_t;
  145.  
  146. int main()
  147. {
  148. PRINT("main");
  149. DummyFiniteStateMachine_t t;
  150. int iTimesToRun=10;
  151. while(t.isGood() && iTimesToRun-->0){t.DispatchCurrentState();}
  152. return 0;
  153. }
Success #stdin #stdout 0s 4572KB
stdin
Standard input is empty
stdout
initStates
completeInitStates
initTransitions
completeInitTransitions
main
DummyMachineClass
FiniteStateMachine
isGood
DispatchCurrentState
init: 0
init2foo
isGood
DispatchCurrentState
foo
foo2bar
isGood
DispatchCurrentState
bar
bar2init
isGood
DispatchCurrentState
init: 1
init2foo
isGood
DispatchCurrentState
foo
foo2bar
isGood
DispatchCurrentState
bar
bar2init
isGood
DispatchCurrentState
init: 2
init2foo
isGood
DispatchCurrentState
foo
foo2bar
isGood
DispatchCurrentState
bar
bar2init
isGood
DispatchCurrentState
init: 3
init2foo
isGood
~FiniteStateMachine
~DummyMachineClass