00001
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
00686 if (m_predo[state.curr] != NULL)
00687 (m_listener->*m_predo [state.curr])(state);
00688
00689 if (need_trans()) return;
00690
00691
00692 if (m_do[state.curr] != NULL)
00693 (m_listener->*m_do [state.curr])(state);
00694
00695 if (need_trans()) return;
00696
00697
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 };
00846
00847 #endif // StateMachine_h