sttcl  v0.9c
STTCL C++ template state machine framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
StateMachine.h
Go to the documentation of this file.
1 
25 #ifndef STATEMACHINE_H_
26 #define STATEMACHINE_H_
27 
28 #include "SttclConfig.h"
29 
30 #include "State.h"
31 #include <cassert>
32 #if defined(STTCL_DEBUG)
33 #include <iostream>
34 //#if defined(STTCL_HAVE_RTTI)
35 #include <typeinfo>
36 //#endif
37 #endif
38 
39 
40 namespace sttcl
41 {
42 
50 template<class StateMachineImpl, class IState>
52 {
56  struct StateMachineFlags
57  {
61  unsigned char initialized:1;
65  unsigned char initializing:1;
69  unsigned char finalized:1;
73  unsigned char finalizing:1;
74 
78  inline StateMachineFlags()
79  : initialized(false)
80  , initializing(false)
81  , finalized(false)
82  , finalizing(false)
83  {
84  }
85  };
86 
87 public:
91  typedef StateMachineImpl Context;
95  typedef IState StateInterface;
100 
101  friend class StateBase<StateMachineImpl,IState>;
102 
107  {
108  if(isInitialized())
109  {
110  finalize();
111  }
112  }
113 
119  bool initialize(bool force = false)
120  {
121  bool result = static_cast<Context*>(this)->initializeImpl(force);
122  return result;
123  }
124 
130  void finalize(bool finalizeSubStateMachines = true)
131  {
132  if(!isFinalizing())
133  {
134  flags.finalizing = true;
135  static_cast<Context*>(this)->finalizeImpl(finalizeSubStateMachines);
136  flags.finalizing = false;
137  }
138  }
139 
144  inline bool isReady() const
145  {
146  return static_cast<const Context*>(this)->isReadyImpl();
147  }
148 
153  bool isInitialized() const
154  {
155  return flags.initialized;
156  }
157 
162  bool isInitalizing() const
163  {
164  return flags.initializing;
165  }
166 
171  bool isFinalized() const
172  {
173  return flags.finalized;
174  }
175 
180  bool isFinalizing() const
181  {
182  return flags.finalizing;
183  }
184 
190  inline StateBaseClass* getState() const
191  {
192  return state;
193  }
194 
200  inline bool initializeImpl(bool force)
201  {
202  if(force || (!isInitialized() && !isInitalizing()))
203  {
204  flags.initializing = true;
205  if(force)
206  {
207  StateBaseClass* currentState = getState();
208  if(currentState)
209  {
210  currentState->finalizeSubStateMachines(true);
211  }
212  if(!isFinalized())
213  {
214  finalize(true);
215  }
216  }
217 
218  StateBaseClass* initialState = getInitialState();
219  if(initialState)
220  {
221  changeState(initialState);
222  }
223  StateBaseClass* currentState = getState();
224  if(currentState)
225  {
226  currentState->initSubStateMachines(force);
227  }
228  flags.initializing = false;
229  flags.finalized = false;
230  flags.initialized = true;
231  }
232  return isReady();
233  }
234 
240  inline void finalizeImpl(bool finalizeSubStateMachines)
241  {
242  if(!isFinalized() && state)
243  {
244  if(finalizeSubStateMachines)
245  {
246  state->finalizeSubStateMachines(true);
247  }
249  }
250  setState(0);
251  flags.finalized = true;
252  flags.initialized = false;
253  }
254 
260  {
261  static_cast<StateMachineImpl*>(this)->subStateMachineCompletedImpl(state);
262  }
263 
269  {
270  }
271 
272 protected:
277  : state(0)
278  , flags()
279  {
280  }
281 
288 
293  inline void setState(StateBaseClass* newState)
294  {
295  state = newState;
296  }
297 
304  {
305  StateBaseClass* result = static_cast<const Context*>(this)->getInitialStateImpl();
306 #if defined(STTCL_DEBUG) // && defined(STTCL_HAVE_RTTI)
307  if(!result)
308  {
309  std::cout << "WARNING: " << typeid(static_cast<const Context*>(this)).name() << ".getInitialStateImpl() returned NULL" << std::endl;
310  }
311 #endif
312  return result;
313  }
314 
315  // Default implementations
316  //---------------------------------------------------------------------------------------
317 
324  {
325  return 0;
326  }
327 
333  inline bool isReadyImpl() const
334  {
335  return flags.initialized && !isFinalized();
336  }
337 
338 
339  void exitCurrentState();
340  void enterNewState();
341 
342 private:
343  StateBaseClass* state;
344  StateMachineFlags flags;
345 
346 };
347 
348 template<class StateMachineImpl, class IState>
350 {
351  if(isInitalizing() || !isFinalized())
352  {
353  if(newState)
354  {
355  if(newState != state)
356  {
357  exitCurrentState();
358  setState(newState);
359  enterNewState();
360  }
361  }
362  else // equivalent to finalize
363  {
364  finalize();
365  }
366  }
367 }
368 
369 template<class StateMachineImpl, class IState>
371 {
372  if(state)
373  {
374  state->endDo(static_cast<StateMachine<StateMachineImpl,IState>::Context*>(this));
375  state->exit(static_cast<StateMachine<StateMachineImpl,IState>::Context*>(this));
376  }
377 }
378 
379 template<class StateMachineImpl, class IState>
381 {
382  state->entry(static_cast<StateMachine<StateMachineImpl,IState>::Context*>(this));
383  state->startDo(static_cast<StateMachine<StateMachineImpl,IState>::Context*>(this));
384 }
385 
386 }
387 
388 #endif /* STATEMACHINE_H_ */