StateMachine.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00019 #ifndef StateMachine_h
00020 #define StateMachine_h
00021 
00022 #include <rtm/RTC.h>
00023 
00024 #include <ace/Guard_T.h>
00025 #include <ace/Thread_Mutex.h>
00026 
00027 namespace RTC_Utils
00028 {
00055   template <class State>
00056   struct StateHolder
00057   {
00058     State curr;
00059     State prev;
00060     State next;
00061   };
00062   
00259   template <class State,
00260             class Listener,
00261             class States = StateHolder<State>, 
00262             class Callback = void (Listener::*)(const States& states)
00263             >
00264   class StateMachine
00265   {
00266   public:
00284     StateMachine(int num_of_state)
00285       : m_num(num_of_state),
00286         m_entry (new Callback[m_num]),
00287         m_predo (new Callback[m_num]),
00288         m_do    (new Callback[m_num]),
00289         m_postdo(new Callback[m_num]),
00290         m_exit  (new Callback[m_num])
00291     {
00292       setNullFunc(m_entry,  NULL);
00293       setNullFunc(m_do,     NULL);
00294       setNullFunc(m_exit,   NULL);
00295       setNullFunc(m_predo,  NULL);
00296       setNullFunc(m_postdo, NULL);
00297       m_transit = NULL;
00298     };
00299     
00317     void setNOP(Callback call_back)
00318     {
00319       setNullFunc(m_entry,  call_back);
00320       setNullFunc(m_do,     call_back);
00321       setNullFunc(m_exit,   call_back);
00322       setNullFunc(m_predo,  call_back);
00323       setNullFunc(m_postdo, call_back);
00324       m_transit = call_back;
00325     }
00326     
00344     void setListener(Listener* listener)
00345     {
00346       m_listener = listener;
00347     }
00348     
00373     bool setEntryAction(State state, Callback call_back)
00374     {
00375       m_entry[state] = call_back;
00376       return true;
00377     }
00378     
00402     bool setPreDoAction(State state, Callback call_back)
00403     {
00404       m_predo[state] = call_back;
00405       return true;
00406     }
00407     
00431     bool setDoAction(State state, Callback call_back)
00432     {
00433       m_do[state] = call_back;
00434       return true;
00435     }
00436     
00460     bool setPostDoAction(State state, Callback call_back)
00461     {
00462       m_postdo[state] = call_back;
00463       return true;
00464     }
00465     
00489     bool setExitAction(State state, Callback call_back)
00490     {
00491       m_exit[state] = call_back;
00492       return true;
00493     }
00494     
00518     bool setTransitionAction(Callback call_back)
00519     {
00520       m_transit = call_back;
00521       return true;
00522     }
00523     
00541     void setStartState(States states)
00542     {
00543       m_states.curr = states.curr;
00544       m_states.prev = states.prev;
00545       m_states.next = states.next;
00546     }
00547     
00568     States getStates()
00569     {
00570       ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00571       return m_states;
00572     }
00573     
00591     State getState()
00592     {
00593       ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00594       return m_states.curr;
00595     }
00596     
00618     bool isIn(State state)
00619     {
00620       ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00621       return m_states.curr == state ? true : false;
00622     }
00623     
00650     void goTo(State state)
00651     {
00652       ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00653       m_states.next = state;
00654       if (m_states.curr == state)
00655         {
00656           m_selftrans  = true;
00657         }
00658     }
00659 
00660     
00677     void worker()
00678     {
00679       States state;
00680       
00681       sync(state);
00682       
00683       if (state.curr == state.next)
00684         {
00685           // pre-do
00686           if (m_predo[state.curr] != NULL)
00687             (m_listener->*m_predo [state.curr])(state);
00688           
00689           if (need_trans()) return;
00690           
00691           // do
00692           if (m_do[state.curr] != NULL)
00693             (m_listener->*m_do    [state.curr])(state);
00694           
00695           if (need_trans()) return;
00696           
00697           // post-do
00698           if (m_postdo[state.curr] != NULL)
00699             (m_listener->*m_postdo[state.curr])(state);
00700         }
00701       else
00702         {
00703           if (m_exit[state.curr] != NULL)
00704             (m_listener->*m_exit[state.curr])(state);
00705           
00706           sync(state);
00707           
00708           if (state.curr != state.next)
00709             {
00710               state.curr = state.next;
00711               if(m_entry[state.curr] != NULL)
00712                 (m_listener->*m_entry[state.curr])(state);
00713               update_curr(state.curr);
00714             }
00715         }
00716     }
00717     
00718   protected:
00738     void setNullFunc(Callback* s, Callback nullfunc)
00739     {
00740       for (int i = 0; i < m_num; ++i) s[i] = nullfunc;
00741     }
00742     
00750     int m_num;
00751     
00759     Listener* m_listener;
00760     
00768     Callback* m_entry;
00769     
00777     Callback* m_predo;
00778     
00786     Callback* m_do;
00787     
00795     Callback* m_postdo;
00796     
00804     Callback* m_exit;
00805     
00813     Callback  m_transit;
00814     
00822     States m_states;
00823     bool m_selftrans;
00824     ACE_Thread_Mutex m_mutex;
00825     
00826   private:
00827     inline void sync(States& st)
00828     {
00829       ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00830       st = m_states;
00831     }
00832     
00833     inline bool need_trans()
00834     {
00835       ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00836       return (m_states.curr != m_states.next);
00837     }
00838     
00839     inline void update_curr(const State curr)
00840     {
00841       ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00842       m_states.curr = curr;
00843     }
00844   };
00845 }; // namespace RTC_Utils
00846 
00847 #endif // StateMachine_h

Generated on Thu May 29 15:03:33 2008 for OpenRTM by  doxygen 1.5.3