sttcl  v0.9c
STTCL C++ template state machine framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ActiveState.h
Go to the documentation of this file.
1 
25 #ifndef ACTIVESTATE_H_
26 #define ACTIVESTATE_H_
27 
28 #include "State.h"
29 #include "SttclThread.h"
30 #include "SttclMutex.h"
31 #include "SttclSemaphore.h"
32 #include "SttclTime.h"
33 
34 namespace sttcl
35 {
36 
37 template
38 < class StateImpl
39 , class StateMachineImpl
40 , class IState
41 , class StateThreadType
42 , class TimeDurationType
43 , class EndDoActionSemaphoreType
44 , class ActiveStateMutexType
45 >
46 class ActiveState;
47 
48 namespace internal
49 {
54 {
76  template
77  < class StateImpl
78  , class StateMachineImpl
79  , class IState
80  , class StateThreadType
81  , class TimeDurationType
82  , class EndDoActionSemaphoreType
83  , class ActiveStateMutexType
84  >
85  static void* stateThreadMethod(void* args)
86  {
87  ActiveState<StateImpl
88  ,StateMachineImpl
89  ,IState
90  ,StateThreadType
91  ,EndDoActionSemaphoreType
92  ,TimeDurationType
93  ,ActiveStateMutexType
94  >* pThis =
95  reinterpret_cast<ActiveState<StateImpl
96  ,StateMachineImpl
97  ,IState
98  ,StateThreadType
99  ,EndDoActionSemaphoreType
100  ,TimeDurationType
101  ,ActiveStateMutexType
102  >*>(args);
103  pThis->runDoAction(pThis->currentContext);
104  return 0;
105  }
106 };
107 }
108 
126 template
127 < class StateImpl
128 , class StateMachineImpl
129 , class IState
131 , class TimeDurationType = TimeDuration<STTCL_DEFAULT_TIMEDURATIONIMPL>
132 , class EndDoActionSemaphoreType = internal::SttclSemaphore<STTCL_DEFAULT_SEMAPHOREIMPL>
133 , class ActiveStateMutexType = internal::SttclMutex<STTCL_DEFAULT_MUTEXIMPL,TimeDurationType>
134 >
136 : public sttcl::StateBase<StateMachineImpl,IState>
137 {
139 public:
143  typedef StateMachineImpl Context;
144 
148  typedef StateImpl Implementation;
149 
154 
158  typedef void (Implementation::*StateDoAction)(Context*, bool);
159 
163  typedef StateThreadType StateThreadImpl;
164 
168  typedef EndDoActionSemaphoreType EndDoActionSemaphoreImpl;
169 
173  typedef TimeDurationType TimeDurationImpl;
174 
178  typedef ActiveStateMutexType ActiveStateMutexImpl;
179 
183  inline const TimeDurationImpl& getDoFrequency() const
184  {
185  return doFrequency;
186  }
187 
191  inline void setDoFrequency(const TimeDurationImpl& newValue)
192  {
193  doFrequency = newValue;
194  }
195 
201  {
202  bool result = endDoActionSemaphore.try_wait(doFrequency);
203  return result;
204  }
205 
210  inline void entryImpl(Context* context)
211  {
212  }
213 
218  inline void exitImpl(Context* context)
219  {
220 
221  }
222 
223 
228  inline void exitingDoActionImpl()
229  {
230  }
231 
236  {
237  if(!StateThreadType::isSelf(stateThread))
238  {
239  stateThread.join();
240  }
241  }
242 
247  inline void unblockDoActionImpl()
248  {
249  }
250 
255  inline void endDoImpl(Context* context)
256  {
257  endDoActionSemaphore.post();
258  if(!StateThreadType::isSelf(stateThread))
259  {
260  if(isDoActionRunning())
261  {
262  static_cast<StateImpl*>(this)->unblockDoActionImpl();
263  }
264  static_cast<Implementation*>(this)->joinDoActionThreadImpl();
265  currentContext = 0;
266  }
267  }
268 
273  inline const StateThreadType& getStateThread() const
274  {
275  return stateThread;
276  }
277 
283  inline void startDoImpl(Context* context)
284  {
285 // if(doAction)
286 // {
287  currentContext = context;
288  stateThread.run(this);
289 // }
290  }
291 
292  inline bool isDoActionRunning() const
293  {
295  return doActionRunning;
296  }
297 
303  void finalizeSubStateMachinesImpl(bool recursive)
304  {
305  }
306 
312  void initSubStateMachinesImpl(bool recursive)
313  {
314  }
315 
323  bool checkDirectTransitionImpl(Context* context, bool& finalize, StateBaseType*& nextState)
324  {
325  nextState = 0;
326  finalize = false;
327  return false;
328  }
329 
330 protected:
341  ActiveState(StateDoAction argDoAction, bool argRunDoActionOnce = false , TimeDurationType argDoFrequency = TimeDurationType::Zero)
342  : doAction(argDoAction)
343  , doFrequency(argDoFrequency)
344  , currentContext(0)
345  , stateThread(&sttcl::internal::ThreadFunctionHelper::stateThreadMethod
346  < StateImpl
347  , StateMachineImpl
348  , IState
349  , StateThreadType
350  , EndDoActionSemaphoreType
351  , TimeDurationType
352  , ActiveStateMutexType>)
353  , endDoActionSemaphore(0)
354  , doActionRunning(false)
355  , runDoActionOnce(argRunDoActionOnce)
356  {
357  }
358 
362  virtual ~ActiveState()
363  {
364  if(isDoActionRunning())
365  {
366  endDo(currentContext);
367  }
368  }
369 
376  {
377  static_cast<Implementation*>(this)->changeStateImpl(context,newState);
378  }
379 
385  {
386  return static_cast<Implementation*>(this)->endDoActionRequestedImpl();
387  }
388 
389 private:
390  virtual void entry(Context* context)
391  {
392  static_cast<Implementation*>(this)->entryImpl(context);
393  }
394 
395  virtual void exit(Context* context)
396  {
397  static_cast<Implementation*>(this)->exitImpl(context);
398  }
399 
400  virtual void startDo(Context* context)
401  {
402  static_cast<Implementation*>(this)->startDoImpl(context);
403  }
404 
405  virtual void endDo(Context* context)
406  {
407  static_cast<Implementation*>(this)->endDoImpl(context);
408  }
409 
410  void setDoActionRunning(bool value)
411  {
413  doActionRunning = value;
414  }
415 
416  void runDoAction(Context* context)
417  {
418  bool initialCall = true;
419  setDoActionRunning(true);
420  bool directTransitionTriggered = false;
421  do
422  {
423  // Run the do action
424  if(doAction)
425  {
426  (static_cast<Implementation*>(this)->*doAction)(context,initialCall);
427  if(initialCall)
428  {
429  initialCall = false;
430  }
431  }
432 
433  // Handle direct transitions
434  StateBaseType* nextState = 0;
435  bool finalize = false;
436  if(static_cast<Implementation*>(this)->checkDirectTransitionImpl(context,finalize,nextState))
437  {
438  if(finalize)
439  {
440  context->finalize();
441  }
442  else if(nextState)
443  {
444  changeState(context,nextState);
445  directTransitionTriggered = true;
446  }
447  }
448  } while(!endDoActionRequested() && !runDoActionOnce && !directTransitionTriggered);
449  static_cast<Implementation*>(this)->exitingDoActionImpl();
450  setDoActionRunning(false);
451  }
452 
453  virtual void finalizeSubStateMachines(bool recursive)
454  {
455  static_cast<Implementation*>(this)->finalizeSubStateMachinesImpl(recursive);
456  }
457 
458  virtual void initSubStateMachines(bool recursive)
459  {
460  static_cast<Implementation*>(this)->initSubStateMachinesImpl(recursive);
461  }
462 
463  StateDoAction doAction;
464  TimeDurationType doFrequency;
465  Context* currentContext;
466  StateThreadType stateThread;
467  EndDoActionSemaphoreType endDoActionSemaphore;
468  mutable ActiveStateMutexType activeStateMutex;
469  bool doActionRunning;
470  bool runDoActionOnce;
471 };
472 
473 }
474 
475 #endif /* ACTIVESTATE_H_ */