00001
00010
00011
00012
00013
00014
00015
00143 #ifndef __robofsm__
00144 #define __robofsm__
00145
00146 #include <stdlib.h>
00147 #include <pthread.h>
00148 #include <semaphore.h>
00149 #include <sys/time.h>
00150 #include <errno.h>
00151 #include "fsm_common_events.h"
00152
00157 typedef int fsm_event;
00158
00159 #ifndef __FSM_ALIASES_DEFINED
00160 #define EV_NOEVENT __COMMON_EV_NOEVENT
00161 #define EV_INIT __COMMON_EV_INIT
00162 #define EV_EXIT __COMMON_EV_EXIT
00163 #define EV_STATE_ENTERED __COMMON_EV_STATE_ENTERED
00164 #define EV_RETURN __COMMON_EV_RETURN
00165 #define EV_TIMEOUT __COMMON_EV_TIMEOUT
00166 #define EV_TIMER __COMMON_EV_TIMER
00167 #endif
00168
00172 struct robo_fsm {
00173 pthread_t threadid;
00179 sem_t event_noticed;
00181 sem_t event_sent;
00183 fsm_event sent_event;
00184 fsm_event event;
00185 struct timespec now;
00186 struct timespec timeout;
00187 struct timespec timer;
00190 int (*state)(struct robo_fsm *fsm);
00191 int (*last_state)(struct robo_fsm *fsm);
00193 int (*fnc_stack[10])(struct robo_fsm *fsm);
00195 int (**fnc_sp)(struct robo_fsm *fsm);
00196 int debug_states;
00197 char *debug_name;
00198 };
00199
00200 #ifdef __cplusplus
00201 extern "C" {
00202 #endif
00203
00204 void fsm_init(struct robo_fsm *fsm, char *debug_name);
00205 int fsm_start(struct robo_fsm *fsm, pthread_attr_t *attr);
00206 int fsm_destroy(struct robo_fsm *fsm);
00207 void __fsm_timespec_add_ms(struct timespec *ts, struct timespec *now, long ms);
00208 void __fsm_timespec_invalidate(struct timespec *ts);
00209
00210
00211
00212
00213
00214 int fsm_nop_state(struct robo_fsm *fsm);
00215
00224 const char *fsm_event_str(fsm_event ev);
00225 const char *fsm_common_event_str(enum fsm_common_events ev);
00226
00230 #define RC_WAIT 0
00231
00233 #define RC_PROC 1
00234
00235
00236 static inline void __fsm_signal(struct robo_fsm *fsm, fsm_event event)
00237 {
00238
00239 sem_wait(&fsm->event_noticed);
00240
00241 fsm->sent_event = event;
00242 sem_post(&fsm->event_sent);
00243 }
00244
00262 #define FSM_SIGNAL(fsm_id, event) __fsm_signal(FSM_GET_BY_ID(fsm_id), __##fsm_id##_##event)
00263
00277 #define DBG_STATE() DBG_FSM_STATE(__FUNCTION__)
00278 #define DBG_FSM_STATE(name) do { if (fsm->debug_states) DBG("fsm %s: %s(%s)\n", fsm->debug_name, name, fsm_event_str(fsm->event)); } while(0)
00279
00283 #define DBG_PRINT_EVENT(msg) DBG("%s: event: %s\n", msg, fsm_event_str(fsm->event))
00284
00285 #ifdef __cplusplus
00286 }
00287 #endif
00288
00289
00290
00291
00292
00312 #define FSM_STATE(name) \
00313 static inline void fsm_state_##name##_impl(struct robo_fsm *fsm, int *__ret); \
00314 int fsm_state_##name(struct robo_fsm *fsm) { \
00315 int ret=RC_WAIT; \
00316 DBG_FSM_STATE(#name); \
00317 fsm_state_##name##_impl(fsm, &ret); \
00318 return ret; \
00319 } \
00320 static inline void fsm_state_##name##_impl(struct robo_fsm *fsm, int *__ret)
00321
00327 #define FSM_STATE_DECL(name) \
00328 int fsm_state_##name(struct robo_fsm *fsm)
00329
00338 #define FSM_TIMEOUT(ms) __fsm_timespec_add_ms(&fsm->timeout, &fsm->now, (ms))
00339
00352 #define FSM_TIMER(ms) __fsm_timespec_add_ms(&fsm->timer, &fsm->now, (ms))
00353
00358 #define FSM_TIMER_STOP() __fsm_timespec_invalidate(&fsm->timer)
00359
00360 #ifndef __FSM_EVENT_ENUM
00361
00362
00363
00364
00365
00366 #define __FSM_EVENT_ENUM enum fsm_common_events
00367 #endif
00368
00372 #define FSM_EVENT ((__FSM_EVENT_ENUM)(fsm->event))
00373
00383 #define FSM_TRANSITION(next) \
00384 do { \
00385 FSM_TIMER_STOP(); \
00386 fsm->last_state = fsm->state; \
00387 fsm->state = &fsm_state_##next; \
00388 fsm->event = EV_STATE_ENTERED; \
00389 *__ret=RC_PROC; \
00390 } while(0)
00391
00401 #define SUBFSM_TRANSITION(substate) \
00402 do { \
00403 FSM_TIMER_STOP(); \
00404 *(fsm->fnc_sp++) = fsm->state; \
00405 fsm->last_state = fsm->state; \
00406 fsm->state = &fsm_state_##substate; \
00407 fsm->event = EV_STATE_ENTERED; \
00408 *__ret = RC_PROC; \
00409 return; \
00410 } while(0)
00411
00416 #define SUBFSM_RET() \
00417 do { \
00418 fsm->last_state = fsm->state; \
00419 fsm->state = *(--fsm->fnc_sp); \
00420 fsm->event = EV_RETURN; \
00421 *__ret = RC_PROC; \
00422 } while(0)
00423
00424 #endif