メインページ | ネームスペース一覧 | クラス階層 | 構成 | Directories | ファイル一覧 | ネームスペースメンバ | 構成メンバ | ファイルメンバ

StateMachine.h

説明を見る。
00001 // -*- C++ -*-
00019 /*
00020  * $Log: StateMachine.h,v $
00021  * Revision 1.3.2.1  2007/07/20 16:08:57  n-ando
00022  * A bug fix.
00023  *
00024  * Revision 1.3  2007/04/26 15:33:39  n-ando
00025  * The header include order was modified to define _REENTRANT before
00026  * including ace/config-lite.h in Linux systems.
00027  * In ace 5.4.7 or later, _REENTRANT flag should be defined explicitly.
00028  *
00029  * Revision 1.2  2007/01/09 15:26:53  n-ando
00030  * Now StateMachine does not need NOP function.
00031  * All null function pointer is checked and skipped.
00032  *
00033  * Revision 1.1  2006/10/26 08:55:53  n-ando
00034  * The first commitment.
00035  *
00036  *
00037  */
00038 
00039 #ifndef StateMachine_h
00040 #define StateMachine_h
00041 
00042 #include <rtm/RTC.h>
00043 
00044 #include <ace/Guard_T.h>
00045 #include <ace/Thread_Mutex.h>
00046 
00047 template <class State>
00048 struct StateHolder
00049 {
00050   State curr;
00051   State prev;
00052   State next;
00053 };
00054 
00147 template <class State, class Result,
00148           class Listener,
00149           class States = StateHolder<State>, 
00150           class Callback = Result (Listener::*)(const States& states)
00151           >
00152 class StateMachine
00153 {
00154 public:
00162   StateMachine(int num_of_state)
00163     : m_num(num_of_state),
00164       m_entry (new Callback[m_num]),
00165       m_predo (new Callback[m_num]),
00166       m_do    (new Callback[m_num]),
00167       m_postdo(new Callback[m_num]),
00168       m_exit  (new Callback[m_num])
00169   {
00170     setNullFunc(m_entry,  NULL);
00171     setNullFunc(m_do,     NULL);
00172     setNullFunc(m_exit,   NULL);
00173     setNullFunc(m_predo,  NULL);
00174     setNullFunc(m_postdo, NULL);
00175     m_transit = NULL;
00176   };
00177 
00178 
00186   void setNOP(Callback call_back)
00187   {
00188     setNullFunc(m_entry,  call_back);
00189     setNullFunc(m_do,     call_back);
00190     setNullFunc(m_exit,   call_back);
00191     setNullFunc(m_predo,  call_back);
00192     setNullFunc(m_postdo, call_back);
00193     m_transit = call_back;
00194   }
00195 
00196 
00204   void setListener(Listener* listener)
00205   {
00206     m_listener = listener;
00207   }
00208 
00209 
00217   bool setEntryAction(State state, Callback call_back)
00218   {
00219     m_entry[state] = call_back;
00220     return true;
00221   }
00222 
00223 
00231   bool setPreDoAction(State state, Callback call_back)
00232   {
00233     m_predo[state] = call_back;
00234     return true;
00235   }
00236 
00237 
00245   bool setDoAction(State state, Callback call_back)
00246   {
00247     m_do[state] = call_back;
00248     return true;
00249     
00250   }
00251 
00252 
00260   bool setPostDoAction(State state, Callback call_back)
00261   {
00262     m_postdo[state] = call_back;
00263     return true;
00264   }
00265 
00266 
00274   bool setExitAction(State state, Callback call_back)
00275   {
00276     m_exit[state] = call_back;
00277     return true;
00278   }
00279 
00280 
00288   bool setTransitionAction(Callback call_back)
00289   {
00290     m_transit = call_back;
00291     return true;
00292   }
00293 
00294 
00302   void setStartState(States states)
00303   {
00304     m_states.curr = states.curr;
00305     m_states.prev = states.prev;
00306     m_states.next = states.next;
00307   }
00308 
00309 
00317   States getStates()
00318   {
00319     ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00320     return m_states;
00321   }
00322   
00323   State getState()
00324   {
00325     ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00326     return m_states.curr;
00327   }
00328   
00329 
00337   bool isIn(State state)
00338   {
00339     ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00340     return m_states.curr == state ? true : false;
00341   }
00342 
00343 
00351   void goTo(State state)
00352   {
00353     ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00354     m_states.next = state;
00355     if (m_states.curr == state)
00356       {
00357         m_selftrans  = true;
00358       }
00359   }
00360 
00361 
00369   Result worker()
00370   {
00371     Result res = RTC::RTC_OK;
00372     States state;
00373     bool selftrans;
00374 
00375     { // lock
00376       ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00377       state = m_states;
00378       selftrans = m_selftrans;
00379       m_selftrans = false;
00380     }
00381 
00382     // Entry アクション
00383     // 前回から状態が変わった
00384     // もしくは自己遷移が行われたのでEntryアクションを行う
00385     if ((state.prev != state.curr) || selftrans)
00386       {
00387         // Entry アクションを実行
00388         if (m_entry[state.curr] != NULL)
00389           res = (m_listener->*m_entry[state.curr])(state);
00390       }
00391 
00392     // この区間では状態の変更を感知しない。
00393     // ただし状態変数 m_states は外部から変更される可能性がある。
00394     // Do アクション判定にはローカル変数を使う。
00395 
00396     // Do アクション
00397     if (state.curr == state.next)
00398       {
00399         if (m_predo[state.curr] != NULL)
00400           res = (m_listener->*m_predo [state.curr])(state);
00401         if (m_do[state.curr] != NULL)
00402           res = (m_listener->*m_do    [state.curr])(state);
00403         if (m_postdo[state.curr] != NULL)
00404           res = (m_listener->*m_postdo[state.curr])(state);
00405       }
00406 
00407     // この区間では次の状態が変更されているかもしれない。
00408     // 状態は m_states.next に反映されている。
00409     // lock
00410     {
00411       ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00412       // 状態のコピー
00413       state.next = m_states.next;
00414       selftrans = m_selftrans;
00415     }
00416 
00417     // Exit アクション
00418     if ((state.curr != state.next) || selftrans)
00419       {
00420         // Exit action of pre-state
00421         if (m_exit[state.curr] != NULL)
00422           res = (m_listener->*m_exit[state.curr])(state);
00423         if (m_transit != NULL)
00424           res = (m_listener->*m_transit)(state);
00425       }
00426 
00427     {
00428       ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00429       // 状態を更新
00430       m_states.prev = m_states.curr;
00431       m_states.curr = m_states.next;
00432     }
00433 
00434     return res;
00435   }
00436 
00437 protected:
00438   void setNullFunc(Callback* s, Callback nullfunc)
00439   {
00440     for (int i = 0; i < m_num; ++i) s[i] = nullfunc;
00441   }
00442 
00443 
00444   int m_num;
00445   Listener* m_listener;
00446   Callback* m_entry;
00447   Callback* m_predo;
00448   Callback* m_do;
00449   Callback* m_postdo;
00450   Callback* m_exit;
00451   Callback  m_transit;
00452 
00453   States m_states;
00454   bool m_selftrans;
00455   ACE_Thread_Mutex m_mutex;
00456 };
00457 
00458 #endif // StateMachine_h

OpenRTMに対してMon Jul 23 17:08:04 2007に生成されました。  doxygen 1.4.1