00001
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef StateMachine_h
00040 #define StateMachine_h
00041
00042 #include <rtm/RTC.h>
00043
00044 #include <ace/Guard_T.h>
00045 #include <ace/Thread_Mutex.h>
00046
00047 template <class State>
00048 struct StateHolder
00049 {
00050 State curr;
00051 State prev;
00052 State next;
00053 };
00054
00147 template <class State, class Result,
00148 class Listener,
00149 class States = StateHolder<State>,
00150 class Callback = Result (Listener::*)(const States& states)
00151 >
00152 class StateMachine
00153 {
00154 public:
00162 StateMachine(int num_of_state)
00163 : m_num(num_of_state),
00164 m_entry (new Callback[m_num]),
00165 m_predo (new Callback[m_num]),
00166 m_do (new Callback[m_num]),
00167 m_postdo(new Callback[m_num]),
00168 m_exit (new Callback[m_num])
00169 {
00170 setNullFunc(m_entry, NULL);
00171 setNullFunc(m_do, NULL);
00172 setNullFunc(m_exit, NULL);
00173 setNullFunc(m_predo, NULL);
00174 setNullFunc(m_postdo, NULL);
00175 m_transit = NULL;
00176 };
00177
00178
00186 void setNOP(Callback call_back)
00187 {
00188 setNullFunc(m_entry, call_back);
00189 setNullFunc(m_do, call_back);
00190 setNullFunc(m_exit, call_back);
00191 setNullFunc(m_predo, call_back);
00192 setNullFunc(m_postdo, call_back);
00193 m_transit = call_back;
00194 }
00195
00196
00204 void setListener(Listener* listener)
00205 {
00206 m_listener = listener;
00207 }
00208
00209
00217 bool setEntryAction(State state, Callback call_back)
00218 {
00219 m_entry[state] = call_back;
00220 return true;
00221 }
00222
00223
00231 bool setPreDoAction(State state, Callback call_back)
00232 {
00233 m_predo[state] = call_back;
00234 return true;
00235 }
00236
00237
00245 bool setDoAction(State state, Callback call_back)
00246 {
00247 m_do[state] = call_back;
00248 return true;
00249
00250 }
00251
00252
00260 bool setPostDoAction(State state, Callback call_back)
00261 {
00262 m_postdo[state] = call_back;
00263 return true;
00264 }
00265
00266
00274 bool setExitAction(State state, Callback call_back)
00275 {
00276 m_exit[state] = call_back;
00277 return true;
00278 }
00279
00280
00288 bool setTransitionAction(Callback call_back)
00289 {
00290 m_transit = call_back;
00291 return true;
00292 }
00293
00294
00302 void setStartState(States states)
00303 {
00304 m_states.curr = states.curr;
00305 m_states.prev = states.prev;
00306 m_states.next = states.next;
00307 }
00308
00309
00317 States getStates()
00318 {
00319 ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00320 return m_states;
00321 }
00322
00323 State getState()
00324 {
00325 ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00326 return m_states.curr;
00327 }
00328
00329
00337 bool isIn(State state)
00338 {
00339 ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00340 return m_states.curr == state ? true : false;
00341 }
00342
00343
00351 void goTo(State state)
00352 {
00353 ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00354 m_states.next = state;
00355 if (m_states.curr == state)
00356 {
00357 m_selftrans = true;
00358 }
00359 }
00360
00361
00369 Result worker()
00370 {
00371 Result res = RTC::RTC_OK;
00372 States state;
00373 bool selftrans;
00374
00375 {
00376 ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00377 state = m_states;
00378 selftrans = m_selftrans;
00379 m_selftrans = false;
00380 }
00381
00382
00383
00384
00385 if ((state.prev != state.curr) || selftrans)
00386 {
00387
00388 if (m_entry[state.curr] != NULL)
00389 res = (m_listener->*m_entry[state.curr])(state);
00390 }
00391
00392
00393
00394
00395
00396
00397 if (state.curr == state.next)
00398 {
00399 if (m_predo[state.curr] != NULL)
00400 res = (m_listener->*m_predo [state.curr])(state);
00401 if (m_do[state.curr] != NULL)
00402 res = (m_listener->*m_do [state.curr])(state);
00403 if (m_postdo[state.curr] != NULL)
00404 res = (m_listener->*m_postdo[state.curr])(state);
00405 }
00406
00407
00408
00409
00410 {
00411 ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00412
00413 state.next = m_states.next;
00414 selftrans = m_selftrans;
00415 }
00416
00417
00418 if ((state.curr != state.next) || selftrans)
00419 {
00420
00421 if (m_exit[state.curr] != NULL)
00422 res = (m_listener->*m_exit[state.curr])(state);
00423 if (m_transit != NULL)
00424 res = (m_listener->*m_transit)(state);
00425 }
00426
00427 {
00428 ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00429
00430 m_states.prev = m_states.curr;
00431 m_states.curr = m_states.next;
00432 }
00433
00434 return res;
00435 }
00436
00437 protected:
00438 void setNullFunc(Callback* s, Callback nullfunc)
00439 {
00440 for (int i = 0; i < m_num; ++i) s[i] = nullfunc;
00441 }
00442
00443
00444 int m_num;
00445 Listener* m_listener;
00446 Callback* m_entry;
00447 Callback* m_predo;
00448 Callback* m_do;
00449 Callback* m_postdo;
00450 Callback* m_exit;
00451 Callback m_transit;
00452
00453 States m_states;
00454 bool m_selftrans;
00455 ACE_Thread_Mutex m_mutex;
00456 };
00457
00458 #endif // StateMachine_h