OpenRTM-aist  1.2.1
StateMachine.h
[詳解]
1 // -*- C++ -*-
19 #ifndef RTC_STATEMACHINE_H
20 #define RTC_STATEMACHINE_H
21 
22 #include <cassert>
23 #include <vector>
24 #include <coil/Mutex.h>
25 #include <coil/Guard.h>
26 
27 namespace RTC_Utils
28 {
55  template <class State>
56  struct StateHolder
57  {
58  State curr;
59  State prev;
60  State next;
61  };
62 
259  template <class State,
260  class Listener,
261  class States = StateHolder<State>,
262  class Callback = void (Listener::*)(const States& states)
263  >
265  {
266  typedef coil::Mutex Mutex;
267  typedef coil::Guard<Mutex> Guard;
268  public:
286  StateMachine(int num_of_state)
287  : m_num(num_of_state),
288  m_listener(NULL),
289  m_entry(m_num, (Callback)NULL),
290  m_predo(m_num, (Callback)NULL),
291  m_do(m_num, (Callback)NULL),
292  m_postdo(m_num, (Callback)NULL),
293  m_exit(m_num, (Callback)NULL),
294  m_transit(NULL)
295  {
296  };
297 
298  virtual ~StateMachine()
299  {
300  };
301 
303  : m_num(other.m_num),
304  m_listener(other.m_listener),
305  m_entry (other.m_entry),
306  m_predo (other.m_predo),
307  m_do (other.m_do),
308  m_postdo(other.m_postdo),
309  m_exit (other.m_exit),
310  m_transit(other.m_transit),
311  m_states(other.m_states),
312  m_selftrans(other.m_selftrans)
313  {
314  }
315 
317  {
318  StateMachine temp(other);
319  swap(temp);
320  return *this;
321  }
322 
323  void swap(StateMachine& other)
324  {
325  std::swap(m_num, other.m_num);
326  std::swap(m_listener, other.m_listener);
327  std::swap(m_entry, other.m_entry);
328  std::swap(m_predo, other.m_predo);
329  std::swap(m_do, other.m_do);
330  std::swap(m_postdo, other.m_postdo);
331  std::swap(m_exit, other.m_exit);
332  std::swap(m_transit, other.m_transit);
333  std::swap(m_states, other.m_states);
334  std::swap(m_selftrans, other.m_selftrans);
335  }
353  void setNOP(Callback call_back)
354  {
355  setNullFunc(m_entry, call_back);
356  setNullFunc(m_do, call_back);
357  setNullFunc(m_exit, call_back);
358  setNullFunc(m_predo, call_back);
359  setNullFunc(m_postdo, call_back);
360  m_transit = call_back;
361  }
362 
380  void setListener(Listener* listener)
381  {
382  assert(listener != NULL);
383  m_listener = listener;
384  }
385 
410  bool setEntryAction(State state, Callback call_back)
411  {
412  try
413  {
414  m_entry.at(state) = call_back;
415  }
416  catch (...)
417  {
418  assert(false);
419  return false;
420  }
421  return true;
422  }
423 
447  bool setPreDoAction(State state, Callback call_back)
448  {
449  try
450  {
451  m_predo.at(state) = call_back;
452  }
453  catch (...)
454  {
455  assert(false);
456  return false;
457  }
458  return true;
459  }
460 
484  bool setDoAction(State state, Callback call_back)
485  {
486  try
487  {
488  m_do.at(state) = call_back;
489  }
490  catch (...)
491  {
492  assert(false);
493  return false;
494  }
495  return true;
496  }
497 
521  bool setPostDoAction(State state, Callback call_back)
522  {
523  try
524  {
525  m_postdo.at(state) = call_back;
526  }
527  catch (...)
528  {
529  assert(false);
530  return false;
531  }
532  return true;
533  }
534 
558  bool setExitAction(State state, Callback call_back)
559  {
560  try
561  {
562  m_exit.at(state) = call_back;
563  }
564  catch (...)
565  {
566  assert(false);
567  return false;
568  }
569  return true;
570  }
571 
595  bool setTransitionAction(Callback call_back)
596  {
597  m_transit = call_back;
598  return true;
599  }
600 
618  void setStartState(States states)
619  {
620  m_states.curr = states.curr;
621  m_states.prev = states.prev;
622  m_states.next = states.next;
623  }
624 
645  States getStates()
646  {
647  Guard guard(m_mutex);
648  return m_states;
649  }
650 
668  State getState()
669  {
670  Guard guard(m_mutex);
671  return m_states.curr;
672  }
673 
695  bool isIn(State state)
696  {
697  Guard guard(m_mutex);
698  return m_states.curr == state ? true : false;
699  }
700 
727  void goTo(State state)
728  {
729  Guard guard(m_mutex);
730  m_states.next = state;
731  if (m_states.curr == state)
732  {
733  m_selftrans = true;
734  }
735  }
736 
737 
754  void worker()
755  {
756  States state;
757 
758  sync(state);
759 
760  if (state.curr == state.next)
761  {
762  // pre-do
763  if (m_predo[state.curr] != NULL)
764  (m_listener->*m_predo [state.curr])(state);
765 
766  if (need_trans()) return;
767 
768  // do
769  if (m_do[state.curr] != NULL)
770  (m_listener->*m_do [state.curr])(state);
771 
772  if (need_trans()) return;
773 
774  // post-do
775  if (m_postdo[state.curr] != NULL)
776  (m_listener->*m_postdo[state.curr])(state);
777  }
778  else
779  {
780  if (m_exit[state.curr] != NULL)
781  (m_listener->*m_exit[state.curr])(state);
782 
783  sync(state);
784 
785  if (state.curr != state.next)
786  {
787  state.curr = state.next;
788  if(m_entry[state.curr] != NULL)
789  (m_listener->*m_entry[state.curr])(state);
790  update_curr(state.curr);
791  }
792  }
793  }
794 
795  //============================================================
796  // divided worker functions
797  // The following divided worker functions have to be used together.
798  // - worker_pre()
799  // - worker_do()
800  // - worker_post()
801  //
802  void worker_pre()
803  {
804  States state;
805  sync(state);
806  if (state.curr == state.next)
807  {
808  if (m_predo[state.curr] != NULL)
809  {
810  (m_listener->*m_predo[state.curr])(state);
811  }
812  return;
813  }
814 
815  // State changed
816  if (m_exit[state.curr] != NULL)
817  {
818  (m_listener->*m_exit[state.curr])(state);
819  }
820  sync(state);
821  if (state.curr != state.next)
822  {
823  state.curr = state.next;
824  if(m_entry[state.curr] != NULL)
825  {
826  (m_listener->*m_entry[state.curr])(state);
827  }
828  update_curr(state.curr);
829  }
830  }
831 
832  void worker_do()
833  {
834  States state;
835  sync(state);
836  if (m_do[state.curr] != NULL)
837  {
838  (m_listener->*m_do[state.curr])(state);
839  }
840  }
841 
842  void worker_post()
843  {
844  States state;
845  sync(state);
846  if (m_postdo[state.curr] != NULL)
847  {
848  (m_listener->*m_postdo[state.curr])(state);
849  }
850  }
851 
852  protected:
872  void setNullFunc(std::vector<Callback>& s, Callback nullfunc)
873  {
874  s.clear();
875  // assert((size_t)m_num == s.size());
876  for (size_t i(0); i < m_num; ++i)
877  {
878  s.push_back(nullfunc);
879  }
880  }
881 
889  int m_num;
890 
898  Listener* m_listener;
899 
907  std::vector<Callback> m_entry;
908 
916  std::vector<Callback> m_predo;
917 
925  std::vector<Callback> m_do;
926 
934  std::vector<Callback> m_postdo;
935 
943  std::vector<Callback> m_exit;
944 
952  Callback m_transit;
953 
961  States m_states;
963  Mutex m_mutex;
964 
965  private:
966  inline void sync(States& st)
967  {
968  Guard guard(m_mutex);
969  st = m_states;
970  }
971 
972  inline bool need_trans()
973  {
974  Guard guard(m_mutex);
975  return (m_states.curr != m_states.next);
976  }
977 
978  inline void update_curr(const State curr)
979  {
980  Guard guard(m_mutex);
981  m_states.curr = curr;
982  }
983  };
984 }; // namespace RTC_Utils
985 
986 #endif // RTC_STATEMACHINE_H
virtual ~StateMachine()
Definition: StateMachine.h:298
bool setDoAction(State state, Callback call_back)
Do action 関数を登録する
Definition: StateMachine.h:484
bool setExitAction(State state, Callback call_back)
Exit action 関数を登録する
Definition: StateMachine.h:558
RTコンポーネント用ユーティリティ関数
Mutex クラス
Definition: Mutex.h:40
bool setPostDoAction(State state, Callback call_back)
PostDo action 関数を登録する
Definition: StateMachine.h:521
void swap(StateMachine &other)
Definition: StateMachine.h:323
States getStates()
状態を取得する
Definition: StateMachine.h:645
std::vector< Callback > m_predo
PreDo action 用コールバック関数
Definition: StateMachine.h:916
StateMachine(const StateMachine &other)
Definition: StateMachine.h:302
void worker_pre()
Definition: StateMachine.h:802
std::vector< Callback > m_do
Do action 用コールバック関数
Definition: StateMachine.h:925
States m_states
現在の状態情報
Definition: StateMachine.h:961
int m_num
状態数
Definition: StateMachine.h:889
std::vector< Callback > m_postdo
PostDo action 用コールバック関数
Definition: StateMachine.h:934
Mutex m_mutex
Definition: StateMachine.h:963
coil::Guard< coil::Mutex > Guard
Definition: LocalServiceAdmin.h:36
void worker()
駆動関数
Definition: StateMachine.h:754
bool setEntryAction(State state, Callback call_back)
Entry action 関数を登録する
Definition: StateMachine.h:410
bool setTransitionAction(Callback call_back)
State transition action 関数を登録する
Definition: StateMachine.h:595
状態マシンクラス
Definition: StateMachine.h:264
void goTo(State state)
状態を遷移
Definition: StateMachine.h:727
std::vector< Callback > m_exit
Exit action 用コールバック関数
Definition: StateMachine.h:943
bool isIn(State state)
現在状態を確認
Definition: StateMachine.h:695
Guard template class.
void setNOP(Callback call_back)
NOP関数を登録する
Definition: StateMachine.h:353
State prev
Definition: StateMachine.h:59
Listener * m_listener
コールバック関数用リスナー
Definition: StateMachine.h:898
状態保持用クラス
Definition: StateMachine.h:56
void setNullFunc(std::vector< Callback > &s, Callback nullfunc)
NOP関数を設定
Definition: StateMachine.h:872
bool setPreDoAction(State state, Callback call_back)
PreDo action 関数を登録する
Definition: StateMachine.h:447
void setStartState(States states)
初期状態をセットする
Definition: StateMachine.h:618
State curr
Definition: StateMachine.h:58
bool m_selftrans
Definition: StateMachine.h:962
StateMachine & operator=(const StateMachine &other)
Definition: StateMachine.h:316
void worker_do()
Definition: StateMachine.h:832
Guard テンプレートクラス
Definition: Guard.h:41
State next
Definition: StateMachine.h:60
void setListener(Listener *listener)
Listener オブジェクトを登録する
Definition: StateMachine.h:380
Callback m_transit
State transition action 用コールバック関数
Definition: StateMachine.h:952
StateMachine(int num_of_state)
コンストラクタ
Definition: StateMachine.h:286
State getState()
現在の状態を取得する
Definition: StateMachine.h:668
std::vector< Callback > m_entry
Entry action 用コールバック関数
Definition: StateMachine.h:907
void worker_post()
Definition: StateMachine.h:842