Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

StateMachine.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00019 /*
00020  * $Log: StateMachine.h,v $
00021  * Revision 1.2  2007/01/09 15:26:53  n-ando
00022  * Now StateMachine does not need NOP function.
00023  * All null function pointer is checked and skipped.
00024  *
00025  * Revision 1.1  2006/10/26 08:55:53  n-ando
00026  * The first commitment.
00027  *
00028  *
00029  */
00030 
00031 #ifndef StateMachine_h
00032 #define StateMachine_h
00033 
00034 #include <ace/Guard_T.h>
00035 #include <ace/Thread_Mutex.h>
00036 
00037 template <class State>
00038 struct StateHolder
00039 {
00040   State curr;
00041   State prev;
00042   State next;
00043 };
00044 
00137 template <class State, class Result,
00138           class Listener,
00139           class States = StateHolder<State>, 
00140           class Callback = Result (Listener::*)(const States& states)
00141           >
00142 class StateMachine
00143 {
00144 public:
00152   StateMachine(int num_of_state)
00153     : m_num(num_of_state),
00154       m_entry (new Callback[m_num]),
00155       m_predo (new Callback[m_num]),
00156       m_do    (new Callback[m_num]),
00157       m_postdo(new Callback[m_num]),
00158       m_exit  (new Callback[m_num])
00159   {
00160     setNullFunc(m_entry,  NULL);
00161     setNullFunc(m_do,     NULL);
00162     setNullFunc(m_exit,   NULL);
00163     setNullFunc(m_predo,  NULL);
00164     setNullFunc(m_postdo, NULL);
00165     m_transit = NULL;
00166   };
00167 
00168 
00176   void setNOP(Callback call_back)
00177   {
00178     setNullFunc(m_entry,  call_back);
00179     setNullFunc(m_do,     call_back);
00180     setNullFunc(m_exit,   call_back);
00181     setNullFunc(m_predo,  call_back);
00182     setNullFunc(m_postdo, call_back);
00183     m_transit = call_back;
00184   }
00185 
00186 
00194   void setListener(Listener* listener)
00195   {
00196     m_listener = listener;
00197   }
00198 
00199 
00207   bool setEntryAction(State state, Callback call_back)
00208   {
00209     m_entry[state] = call_back;
00210     return true;
00211   }
00212 
00213 
00221   bool setPreDoAction(State state, Callback call_back)
00222   {
00223     m_predo[state] = call_back;
00224     return true;
00225   }
00226 
00227 
00235   bool setDoAction(State state, Callback call_back)
00236   {
00237     m_do[state] = call_back;
00238     return true;
00239     
00240   }
00241 
00242 
00250   bool setPostDoAction(State state, Callback call_back)
00251   {
00252     m_postdo[state] = call_back;
00253     return true;
00254   }
00255 
00256 
00264   bool setExitAction(State state, Callback call_back)
00265   {
00266     m_exit[state] = call_back;
00267     return true;
00268   }
00269 
00270 
00278   bool setTransitionAction(Callback call_back)
00279   {
00280     m_transit = call_back;
00281     return true;
00282   }
00283 
00284 
00292   void setStartState(States states)
00293   {
00294     m_states.curr = states.curr;
00295     m_states.prev = states.prev;
00296     m_states.next = states.next;
00297   }
00298 
00299 
00307   States getStates()
00308   {
00309     ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00310     return m_states;
00311   }
00312   
00313   State getState()
00314   {
00315     ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00316     return m_states.curr;
00317   }
00318   
00319 
00327   bool isIn(State state)
00328   {
00329     ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00330     return m_states.curr == state ? true : false;
00331   }
00332 
00333 
00341   void goTo(State state)
00342   {
00343     ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00344     m_states.next = state;
00345     if (m_states.curr == state)
00346       {
00347         m_selftrans  = true;
00348       }
00349   }
00350 
00351 
00359   Result worker()
00360   {
00361     Result res;
00362     States state;
00363     bool selftrans;
00364 
00365     { // lock
00366       ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00367       state = m_states;
00368       selftrans = m_selftrans;
00369       m_selftrans = false;
00370     }
00371 
00372     // Entry アクション
00373     // 前回から状態が変わった
00374     // もしくは自己遷移が行われたのでEntryアクションを行う
00375     if ((state.prev != state.curr) || selftrans)
00376       {
00377         // Entry アクションを実行
00378         if (m_entry[state.curr] != NULL)
00379           res = (m_listener->*m_entry[state.curr])(state);
00380       }
00381 
00382     // この区間では状態の変更を感知しない。
00383     // ただし状態変数 m_states は外部から変更される可能性がある。
00384     // Do アクション判定にはローカル変数を使う。
00385 
00386     // Do アクション
00387     if (state.curr == state.next)
00388       {
00389         if (m_predo[state.curr] != NULL)
00390           res = (m_listener->*m_predo [state.curr])(state);
00391         if (m_do[state.curr] != NULL)
00392           res = (m_listener->*m_do    [state.curr])(state);
00393         if (m_postdo[state.curr] != NULL)
00394           res = (m_listener->*m_postdo[state.curr])(state);
00395       }
00396 
00397     // この区間では次の状態が変更されているかもしれない。
00398     // 状態は m_states.next に反映されている。
00399     // lock
00400     {
00401       ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00402       // 状態のコピー
00403       state.next = m_states.next;
00404       selftrans = m_selftrans;
00405     }
00406 
00407     // Exit アクション
00408     if ((state.curr != state.next) || selftrans)
00409       {
00410         // Exit action of pre-state
00411         if (m_exit[state.curr] != NULL)
00412           res = (m_listener->*m_exit[state.curr])(state);
00413         if (m_transit != NULL)
00414           res = (m_listener->*m_transit)(state);
00415       }
00416 
00417     {
00418       ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00419       // 状態を更新
00420       m_states.prev = m_states.curr;
00421       m_states.curr = m_states.next;
00422     }
00423 
00424     return res;
00425   }
00426 
00427 protected:
00428   void setNullFunc(Callback* s, Callback nullfunc)
00429   {
00430     for (int i = 0; i < m_num; ++i) s[i] = nullfunc;
00431   }
00432 
00433 
00434   int m_num;
00435   Listener* m_listener;
00436   Callback* m_entry;
00437   Callback* m_predo;
00438   Callback* m_do;
00439   Callback* m_postdo;
00440   Callback* m_exit;
00441   Callback  m_transit;
00442 
00443   States m_states;
00444   bool m_selftrans;
00445   ACE_Thread_Mutex m_mutex;
00446 };
00447 
00448 #endif // StateMachine_h

Generated on Mon Jan 15 12:15:35 2007 for OpenRTM by  doxygen 1.4.1