OpenRTM-aist 2.0.2
Loading...
Searching...
No Matches
StateMachine.h
Go to the documentation of this file.
1// -*- C++ -*-
19#ifndef RTC_STATEMACHINE_H
20#define RTC_STATEMACHINE_H
21
22#include <mutex>
23
24#include <cassert>
25#include <utility>
26#include <vector>
27
28namespace RTC_Utils
29{
56 template <class State>
58 {
59 State curr;
60 State prev;
61 State next;
62 };
63
261 template <class State,
262 class Listener,
263 class States = StateHolder<State>,
264 class Callback = void (Listener::*)(const States& states)
265 >
267 {
268 public:
286 explicit StateMachine(int num_of_state)
287 : m_num(num_of_state),
288 m_listener(nullptr),
289 m_entry(m_num, (Callback)nullptr),
290 m_predo(m_num, (Callback)nullptr),
291 m_do(m_num, (Callback)nullptr),
292 m_postdo(m_num, (Callback)nullptr),
293 m_exit(m_num, (Callback)nullptr),
294 m_transit(nullptr),
295 m_selftrans(false)
296 {
297 }
298
299 virtual ~StateMachine();
300
302 : m_num(other.m_num),
303 m_listener(other.m_listener),
304 m_entry (other.m_entry),
305 m_predo (other.m_predo),
306 m_do (other.m_do),
307 m_postdo(other.m_postdo),
308 m_exit (other.m_exit),
309 m_transit(other.m_transit),
310 m_states(other.m_states),
311 m_selftrans(other.m_selftrans)
312 {
313 }
314
316 {
317 StateMachine temp(other);
318 swap(temp);
319 return *this;
320 }
321
322 void swap(StateMachine& other)
323 {
324 std::swap(m_num, other.m_num);
325 std::swap(m_listener, other.m_listener);
326 std::swap(m_entry, other.m_entry);
327 std::swap(m_predo, other.m_predo);
328 std::swap(m_do, other.m_do);
329 std::swap(m_postdo, other.m_postdo);
330 std::swap(m_exit, other.m_exit);
331 std::swap(m_transit, other.m_transit);
332 std::swap(m_states, other.m_states);
333 std::swap(m_selftrans, other.m_selftrans);
334 }
352 void setNOP(Callback call_back)
353 {
354 setNullFunc(m_entry, call_back);
355 setNullFunc(m_do, call_back);
356 setNullFunc(m_exit, call_back);
357 setNullFunc(m_predo, call_back);
358 setNullFunc(m_postdo, call_back);
359 m_transit = call_back;
360 }
361
379 void setListener(Listener* listener)
380 {
381 assert(listener != nullptr);
382 m_listener = listener;
383 }
384
409 bool setEntryAction(State state, Callback call_back)
410 {
411 try
412 {
413 m_entry.at(state) = call_back;
414 }
415 catch (...)
416 {
417 assert(false);
418 return false;
419 }
420 return true;
421 }
422
446 bool setPreDoAction(State state, Callback call_back)
447 {
448 try
449 {
450 m_predo.at(state) = call_back;
451 }
452 catch (...)
453 {
454 assert(false);
455 return false;
456 }
457 return true;
458 }
459
483 bool setDoAction(State state, Callback call_back)
484 {
485 try
486 {
487 m_do.at(state) = call_back;
488 }
489 catch (...)
490 {
491 assert(false);
492 return false;
493 }
494 return true;
495 }
496
520 bool setPostDoAction(State state, Callback call_back)
521 {
522 try
523 {
524 m_postdo.at(state) = call_back;
525 }
526 catch (...)
527 {
528 assert(false);
529 return false;
530 }
531 return true;
532 }
533
557 bool setExitAction(State state, Callback call_back)
558 {
559 try
560 {
561 m_exit.at(state) = call_back;
562 }
563 catch (...)
564 {
565 assert(false);
566 return false;
567 }
568 return true;
569 }
570
594 bool setTransitionAction(Callback call_back)
595 {
596 m_transit = call_back;
597 return true;
598 }
599
617 void setStartState(States states)
618 {
619 m_states.curr = states.curr;
620 m_states.prev = states.prev;
621 m_states.next = states.next;
622 }
623
644 States getStates()
645 {
646 std::lock_guard<std::mutex> guard(m_mutex);
647 return m_states;
648 }
649
667 State getState()
668 {
669 std::lock_guard<std::mutex> guard(m_mutex);
670 return m_states.curr;
671 }
672
694 bool isIn(State state)
695 {
696 std::lock_guard<std::mutex> guard(m_mutex);
697 return m_states.curr == state ? true : false;
698 }
699
726 void goTo(State state)
727 {
728 std::lock_guard<std::mutex> guard(m_mutex);
729 m_states.next = state;
730 if (m_states.curr == state)
731 {
732 m_selftrans = true;
733 }
734 }
735
736
753 void worker()
754 {
755 States state;
756
757 sync(state);
758
759 if (state.curr == state.next)
760 {
761 // pre-do
762 if (m_predo[state.curr] != NULL)
763 (m_listener->*m_predo[state.curr])(state);
764
765 if (need_trans()) return;
766
767 // do
768 if (m_do[state.curr] != NULL)
769 (m_listener->*m_do[state.curr])(state);
770
771 if (need_trans()) return;
772
773 // post-do
774 if (m_postdo[state.curr] != NULL)
775 (m_listener->*m_postdo[state.curr])(state);
776 }
777 else
778 {
779 if (m_exit[state.curr] != NULL)
780 (m_listener->*m_exit[state.curr])(state);
781
782 sync(state);
783
784 if (state.curr != state.next)
785 {
786 state.curr = state.next;
787 if (m_entry[state.curr] != NULL)
788 (m_listener->*m_entry[state.curr])(state);
789 update_curr(state.curr);
790 }
791 }
792 }
793
794 //============================================================
795 // divided worker functions
796 // The following divided worker functions have to be used together.
797 // - worker_pre()
798 // - worker_do()
799 // - worker_post()
800 //
802 {
803 States state;
804 sync(state);
805 if (state.curr == state.next)
806 {
807 if (m_predo[state.curr] != nullptr)
808 {
809 (m_listener->*m_predo[state.curr])(state);
810 }
811 return;
812 }
813
814 // State changed
815 if (m_exit[state.curr] != nullptr)
816 {
817 (m_listener->*m_exit[state.curr])(state);
818 }
819 sync(state);
820 if (state.curr != state.next)
821 {
822 state.curr = state.next;
823 if (m_entry[state.curr] != nullptr)
824 {
825 (m_listener->*m_entry[state.curr])(state);
826 }
827 update_curr(state.curr);
828 }
829 }
830
832 {
833 States state;
834 sync(state);
835 if (m_do[state.curr] != nullptr)
836 {
837 (m_listener->*m_do[state.curr])(state);
838 }
839 }
840
842 {
843 States state;
844 sync(state);
845 if (m_postdo[state.curr] != nullptr)
846 {
847 (m_listener->*m_postdo[state.curr])(state);
848 }
849 }
850
851 protected:
871 void setNullFunc(std::vector<Callback>& s, Callback nullfunc)
872 {
873 s.clear();
874 for (size_t i(0); i < m_num; ++i)
875 {
876 s.emplace_back(nullfunc);
877 }
878 }
879
887 int m_num;
888
897
905 std::vector<Callback> m_entry;
906
914 std::vector<Callback> m_predo;
915
923 std::vector<Callback> m_do;
924
932 std::vector<Callback> m_postdo;
933
941 std::vector<Callback> m_exit;
942
950 Callback m_transit;
951
959 States m_states;
961 std::mutex m_mutex;
962
963 private:
964 inline void sync(States& st)
965 {
966 std::lock_guard<std::mutex> guard(m_mutex);
967 st = m_states;
968 }
969
970 inline bool need_trans()
971 {
972 std::lock_guard<std::mutex> guard(m_mutex);
973 return (m_states.curr != m_states.next);
974 }
975
976 inline void update_curr(const State curr)
977 {
978 std::lock_guard<std::mutex> guard(m_mutex);
979 m_states.curr = curr;
980 }
981 };
982
983 // No inline for gcc warning, too big
984 template <class T, class U, class V, class W>
986
987} // namespace RTC_Utils
988
989#endif // RTC_STATEMACHINE_H
State machine class.
Definition StateMachine.h:267
void setNOP(Callback call_back)
Set NOP function.
Definition StateMachine.h:352
State getState()
Get current state.
Definition StateMachine.h:667
bool setTransitionAction(Callback call_back)
Set state transition action function.
Definition StateMachine.h:594
int m_num
Number of state .
Definition StateMachine.h:887
Listener * m_listener
Callback function for listener .
Definition StateMachine.h:896
States m_states
Current state information .
Definition StateMachine.h:959
void worker_pre()
Definition StateMachine.h:801
void worker_post()
Definition StateMachine.h:841
void setNullFunc(std::vector< Callback > &s, Callback nullfunc)
Set NOP function.
Definition StateMachine.h:871
bool setDoAction(State state, Callback call_back)
Set Do action function.
Definition StateMachine.h:483
void goTo(State state)
Transit State.
Definition StateMachine.h:726
void swap(StateMachine &other)
Definition StateMachine.h:322
std::vector< Callback > m_postdo
Callback function for PostDo action .
Definition StateMachine.h:932
void setStartState(States states)
Set the initial state.
Definition StateMachine.h:617
std::mutex m_mutex
Definition StateMachine.h:961
bool setEntryAction(State state, Callback call_back)
Set Entry action function.
Definition StateMachine.h:409
bool isIn(State state)
Check current state.
Definition StateMachine.h:694
std::vector< Callback > m_exit
Callback function for Exit action .
Definition StateMachine.h:941
std::vector< Callback > m_entry
Callback function for Entry action .
Definition StateMachine.h:905
bool setPreDoAction(State state, Callback call_back)
Set PreDo action function.
Definition StateMachine.h:446
void worker_do()
Definition StateMachine.h:831
StateMachine(const StateMachine &other)
Definition StateMachine.h:301
bool m_selftrans
Definition StateMachine.h:960
Callback m_transit
Callback function for State transition action .
Definition StateMachine.h:950
std::vector< Callback > m_do
Callback function for Do action .
Definition StateMachine.h:923
bool setPostDoAction(State state, Callback call_back)
Set PostDo action function.
Definition StateMachine.h:520
bool setExitAction(State state, Callback call_back)
Set Exit action function.
Definition StateMachine.h:557
StateMachine(int num_of_state)
Constructor.
Definition StateMachine.h:286
std::vector< Callback > m_predo
Callback function for PreDo action .
Definition StateMachine.h:914
States getStates()
Get states.
Definition StateMachine.h:644
void worker()
Worker function.
Definition StateMachine.h:753
void setListener(Listener *listener)
Set Listener Object.
Definition StateMachine.h:379
StateMachine & operator=(const StateMachine &other)
Definition StateMachine.h:315
Utility functions for RT-Component.
State holder class.
Definition StateMachine.h:58
State curr
Definition StateMachine.h:59
State prev
Definition StateMachine.h:60
State next
Definition StateMachine.h:61