00001
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef StateMachine_h
00037 #define StateMachine_h
00038
00039 #include <rtm/RTC.h>
00040
00041 #include <ace/Guard_T.h>
00042 #include <ace/Thread_Mutex.h>
00043
00044 template <class State>
00045 struct StateHolder
00046 {
00047 State curr;
00048 State prev;
00049 State next;
00050 };
00051
00144 template <class State, class Result,
00145 class Listener,
00146 class States = StateHolder<State>,
00147 class Callback = Result (Listener::*)(const States& states)
00148 >
00149 class StateMachine
00150 {
00151 public:
00159 StateMachine(int num_of_state)
00160 : m_num(num_of_state),
00161 m_entry (new Callback[m_num]),
00162 m_predo (new Callback[m_num]),
00163 m_do (new Callback[m_num]),
00164 m_postdo(new Callback[m_num]),
00165 m_exit (new Callback[m_num])
00166 {
00167 setNullFunc(m_entry, NULL);
00168 setNullFunc(m_do, NULL);
00169 setNullFunc(m_exit, NULL);
00170 setNullFunc(m_predo, NULL);
00171 setNullFunc(m_postdo, NULL);
00172 m_transit = NULL;
00173 };
00174
00175
00183 void setNOP(Callback call_back)
00184 {
00185 setNullFunc(m_entry, call_back);
00186 setNullFunc(m_do, call_back);
00187 setNullFunc(m_exit, call_back);
00188 setNullFunc(m_predo, call_back);
00189 setNullFunc(m_postdo, call_back);
00190 m_transit = call_back;
00191 }
00192
00193
00201 void setListener(Listener* listener)
00202 {
00203 m_listener = listener;
00204 }
00205
00206
00214 bool setEntryAction(State state, Callback call_back)
00215 {
00216 m_entry[state] = call_back;
00217 return true;
00218 }
00219
00220
00228 bool setPreDoAction(State state, Callback call_back)
00229 {
00230 m_predo[state] = call_back;
00231 return true;
00232 }
00233
00234
00242 bool setDoAction(State state, Callback call_back)
00243 {
00244 m_do[state] = call_back;
00245 return true;
00246
00247 }
00248
00249
00257 bool setPostDoAction(State state, Callback call_back)
00258 {
00259 m_postdo[state] = call_back;
00260 return true;
00261 }
00262
00263
00271 bool setExitAction(State state, Callback call_back)
00272 {
00273 m_exit[state] = call_back;
00274 return true;
00275 }
00276
00277
00285 bool setTransitionAction(Callback call_back)
00286 {
00287 m_transit = call_back;
00288 return true;
00289 }
00290
00291
00299 void setStartState(States states)
00300 {
00301 m_states.curr = states.curr;
00302 m_states.prev = states.prev;
00303 m_states.next = states.next;
00304 }
00305
00306
00314 States getStates()
00315 {
00316 ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00317 return m_states;
00318 }
00319
00320 State getState()
00321 {
00322 ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00323 return m_states.curr;
00324 }
00325
00326
00334 bool isIn(State state)
00335 {
00336 ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00337 return m_states.curr == state ? true : false;
00338 }
00339
00340
00348 void goTo(State state)
00349 {
00350 ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00351 m_states.next = state;
00352 if (m_states.curr == state)
00353 {
00354 m_selftrans = true;
00355 }
00356 }
00357
00358
00366 Result worker()
00367 {
00368 Result res;
00369 States state;
00370 bool selftrans;
00371
00372 {
00373 ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00374 state = m_states;
00375 selftrans = m_selftrans;
00376 m_selftrans = false;
00377 }
00378
00379
00380
00381
00382 if ((state.prev != state.curr) || selftrans)
00383 {
00384
00385 if (m_entry[state.curr] != NULL)
00386 res = (m_listener->*m_entry[state.curr])(state);
00387 }
00388
00389
00390
00391
00392
00393
00394 if (state.curr == state.next)
00395 {
00396 if (m_predo[state.curr] != NULL)
00397 res = (m_listener->*m_predo [state.curr])(state);
00398 if (m_do[state.curr] != NULL)
00399 res = (m_listener->*m_do [state.curr])(state);
00400 if (m_postdo[state.curr] != NULL)
00401 res = (m_listener->*m_postdo[state.curr])(state);
00402 }
00403
00404
00405
00406
00407 {
00408 ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00409
00410 state.next = m_states.next;
00411 selftrans = m_selftrans;
00412 }
00413
00414
00415 if ((state.curr != state.next) || selftrans)
00416 {
00417
00418 if (m_exit[state.curr] != NULL)
00419 res = (m_listener->*m_exit[state.curr])(state);
00420 if (m_transit != NULL)
00421 res = (m_listener->*m_transit)(state);
00422 }
00423
00424 {
00425 ACE_Guard<ACE_Thread_Mutex> guard(m_mutex);
00426
00427 m_states.prev = m_states.curr;
00428 m_states.curr = m_states.next;
00429 }
00430
00431 return res;
00432 }
00433
00434 protected:
00435 void setNullFunc(Callback* s, Callback nullfunc)
00436 {
00437 for (int i = 0; i < m_num; ++i) s[i] = nullfunc;
00438 }
00439
00440
00441 int m_num;
00442 Listener* m_listener;
00443 Callback* m_entry;
00444 Callback* m_predo;
00445 Callback* m_do;
00446 Callback* m_postdo;
00447 Callback* m_exit;
00448 Callback m_transit;
00449
00450 States m_states;
00451 bool m_selftrans;
00452 ACE_Thread_Mutex m_mutex;
00453 };
00454
00455 #endif // StateMachine_h