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