00001
00019 #ifndef RTC_STATEMACHINE_H
00020 #define RTC_STATEMACHINE_H
00021
00022 #include <cassert>
00023 #include <vector>
00024 #include <coil/Mutex.h>
00025 #include <coil/Guard.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 typedef coil::Mutex Mutex;
00267 typedef coil::Guard<Mutex> Guard;
00268 public:
00286 StateMachine(int num_of_state)
00287 : m_num(num_of_state),
00288 m_listener(NULL),
00289 m_entry(m_num, (Callback)NULL),
00290 m_predo(m_num, (Callback)NULL),
00291 m_do(m_num, (Callback)NULL),
00292 m_postdo(m_num, (Callback)NULL),
00293 m_exit(m_num, (Callback)NULL),
00294 m_transit(NULL)
00295 {
00296 };
00297
00298 virtual ~StateMachine()
00299 {
00300 };
00301
00302 StateMachine(const StateMachine& other)
00303 : m_num(other.m_num),
00304 m_listener(other.m_listener),
00305 m_entry (other.m_entry),
00306 m_predo (other.m_predo),
00307 m_do (other.m_do),
00308 m_postdo(other.m_postdo),
00309 m_exit (other.m_exit),
00310 m_transit(other.m_transit),
00311 m_states(other.m_states),
00312 m_selftrans(other.m_selftrans)
00313 {
00314 }
00315
00316 StateMachine& operator=(const StateMachine& other)
00317 {
00318 StateMachine temp(other);
00319 swap(temp);
00320 return *this;
00321 }
00322
00323 void swap(StateMachine& other)
00324 {
00325 std::swap(m_num, other.m_num);
00326 std::swap(m_listener, other.m_listener);
00327 std::swap(m_entry, other.m_entry);
00328 std::swap(m_predo, other.m_predo);
00329 std::swap(m_do, other.m_do);
00330 std::swap(m_postdo, other.m_postdo);
00331 std::swap(m_exit, other.m_exit);
00332 std::swap(m_transit, other.m_transit);
00333 std::swap(m_states, other.m_states);
00334 std::swap(m_selftrans, other.m_selftrans);
00335 }
00353 void setNOP(Callback call_back)
00354 {
00355 setNullFunc(m_entry, call_back);
00356 setNullFunc(m_do, call_back);
00357 setNullFunc(m_exit, call_back);
00358 setNullFunc(m_predo, call_back);
00359 setNullFunc(m_postdo, call_back);
00360 m_transit = call_back;
00361 }
00362
00380 void setListener(Listener* listener)
00381 {
00382 assert(listener != NULL);
00383 m_listener = listener;
00384 }
00385
00410 bool setEntryAction(State state, Callback call_back)
00411 {
00412 try
00413 {
00414 m_entry.at(state) = call_back;
00415 }
00416 catch (...)
00417 {
00418 assert(false);
00419 return false;
00420 }
00421 return true;
00422 }
00423
00447 bool setPreDoAction(State state, Callback call_back)
00448 {
00449 try
00450 {
00451 m_predo.at(state) = call_back;
00452 }
00453 catch (...)
00454 {
00455 assert(false);
00456 return false;
00457 }
00458 return true;
00459 }
00460
00484 bool setDoAction(State state, Callback call_back)
00485 {
00486 try
00487 {
00488 m_do.at(state) = call_back;
00489 }
00490 catch (...)
00491 {
00492 assert(false);
00493 return false;
00494 }
00495 return true;
00496 }
00497
00521 bool setPostDoAction(State state, Callback call_back)
00522 {
00523 try
00524 {
00525 m_postdo.at(state) = call_back;
00526 }
00527 catch (...)
00528 {
00529 assert(false);
00530 return false;
00531 }
00532 return true;
00533 }
00534
00558 bool setExitAction(State state, Callback call_back)
00559 {
00560 try
00561 {
00562 m_exit.at(state) = call_back;
00563 }
00564 catch (...)
00565 {
00566 assert(false);
00567 return false;
00568 }
00569 return true;
00570 }
00571
00595 bool setTransitionAction(Callback call_back)
00596 {
00597 m_transit = call_back;
00598 return true;
00599 }
00600
00618 void setStartState(States states)
00619 {
00620 m_states.curr = states.curr;
00621 m_states.prev = states.prev;
00622 m_states.next = states.next;
00623 }
00624
00645 States getStates()
00646 {
00647 Guard guard(m_mutex);
00648 return m_states;
00649 }
00650
00668 State getState()
00669 {
00670 Guard guard(m_mutex);
00671 return m_states.curr;
00672 }
00673
00695 bool isIn(State state)
00696 {
00697 Guard guard(m_mutex);
00698 return m_states.curr == state ? true : false;
00699 }
00700
00727 void goTo(State state)
00728 {
00729 Guard guard(m_mutex);
00730 m_states.next = state;
00731 if (m_states.curr == state)
00732 {
00733 m_selftrans = true;
00734 }
00735 }
00736
00737
00754 void worker()
00755 {
00756 States state;
00757
00758 sync(state);
00759
00760 if (state.curr == state.next)
00761 {
00762
00763 if (m_predo[state.curr] != NULL)
00764 (m_listener->*m_predo [state.curr])(state);
00765
00766 if (need_trans()) return;
00767
00768
00769 if (m_do[state.curr] != NULL)
00770 (m_listener->*m_do [state.curr])(state);
00771
00772 if (need_trans()) return;
00773
00774
00775 if (m_postdo[state.curr] != NULL)
00776 (m_listener->*m_postdo[state.curr])(state);
00777 }
00778 else
00779 {
00780 if (m_exit[state.curr] != NULL)
00781 (m_listener->*m_exit[state.curr])(state);
00782
00783 sync(state);
00784
00785 if (state.curr != state.next)
00786 {
00787 state.curr = state.next;
00788 if(m_entry[state.curr] != NULL)
00789 (m_listener->*m_entry[state.curr])(state);
00790 update_curr(state.curr);
00791 }
00792 }
00793 }
00794
00795
00796
00797
00798
00799
00800
00801
00802 void worker_pre()
00803 {
00804 States state;
00805 sync(state);
00806 if (state.curr == state.next)
00807 {
00808 if (m_predo[state.curr] != NULL)
00809 {
00810 (m_listener->*m_predo[state.curr])(state);
00811 }
00812 return;
00813 }
00814
00815
00816 if (m_exit[state.curr] != NULL)
00817 {
00818 (m_listener->*m_exit[state.curr])(state);
00819 }
00820 sync(state);
00821 if (state.curr != state.next)
00822 {
00823 state.curr = state.next;
00824 if(m_entry[state.curr] != NULL)
00825 {
00826 (m_listener->*m_entry[state.curr])(state);
00827 }
00828 update_curr(state.curr);
00829 }
00830 }
00831
00832 void worker_do()
00833 {
00834 States state;
00835 sync(state);
00836 if (m_do[state.curr] != NULL)
00837 {
00838 (m_listener->*m_do[state.curr])(state);
00839 }
00840 }
00841
00842 void worker_post()
00843 {
00844 States state;
00845 sync(state);
00846 if (m_postdo[state.curr] != NULL)
00847 {
00848 (m_listener->*m_postdo[state.curr])(state);
00849 }
00850 }
00851
00852 protected:
00872 void setNullFunc(std::vector<Callback>& s, Callback nullfunc)
00873 {
00874 s.clear();
00875
00876 for (size_t i(0); i < m_num; ++i)
00877 {
00878 s.push_back(nullfunc);
00879 }
00880 }
00881
00889 int m_num;
00890
00898 Listener* m_listener;
00899
00907 std::vector<Callback> m_entry;
00908
00916 std::vector<Callback> m_predo;
00917
00925 std::vector<Callback> m_do;
00926
00934 std::vector<Callback> m_postdo;
00935
00943 std::vector<Callback> m_exit;
00944
00952 Callback m_transit;
00953
00961 States m_states;
00962 bool m_selftrans;
00963 Mutex m_mutex;
00964
00965 private:
00966 inline void sync(States& st)
00967 {
00968 Guard guard(m_mutex);
00969 st = m_states;
00970 }
00971
00972 inline bool need_trans()
00973 {
00974 Guard guard(m_mutex);
00975 return (m_states.curr != m_states.next);
00976 }
00977
00978 inline void update_curr(const State curr)
00979 {
00980 Guard guard(m_mutex);
00981 m_states.curr = curr;
00982 }
00983 };
00984 };
00985
00986 #endif // RTC_STATEMACHINE_H