加入状态机
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
#ifndef INCLUDED_GAI_FSM_H
|
||||
#define INCLUDED_GAI_FSM_H
|
||||
|
||||
#ifndef INCLUDED_OS_TYPES_H
|
||||
#include <os_types.h>
|
||||
#endif /*INCLUDED_OS_TYPES_H*/
|
||||
|
||||
#ifndef INCLUDED_OS_COMPILER_H
|
||||
#include <os_compiler.h>
|
||||
#endif /*INCLUDED_OS_COMPILER_H*/
|
||||
|
||||
#ifndef INCLUDED_OS_LIST_H
|
||||
#include <os_list.h>
|
||||
#endif /*INCLUDED_OS_LIST_H*/
|
||||
|
||||
#ifndef INCLUDED_GAI_ACTION_H
|
||||
#include <gai_action.h>
|
||||
#endif /*INCLUDED_GAI_ACTION_H*/
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
typedef struct gai_fsm_state_t gai_fsm_state_t;
|
||||
typedef struct gai_fsm_transition_t gai_fsm_transition_t;
|
||||
typedef struct gai_fsm_t gai_fsm_t;
|
||||
|
||||
typedef os_bool_t (*gai_fsm_evaluator_t)(gai_fsm_t* self, gai_fsm_transition_t* transition, void* ud);
|
||||
|
||||
struct gai_fsm_state_t{
|
||||
os_list_node_t node;
|
||||
os_int_t id;
|
||||
os_list_t transition_list;
|
||||
gai_action_t action;
|
||||
};
|
||||
|
||||
struct gai_fsm_transition_t{
|
||||
os_list_node_t node;
|
||||
os_int_t from_state_id;
|
||||
os_int_t to_state_id;
|
||||
gai_fsm_evaluator_t evaluator;
|
||||
void* userdata;
|
||||
};
|
||||
|
||||
struct gai_fsm_t{
|
||||
gai_fsm_state_t* current_state_p;
|
||||
os_list_t state_list;
|
||||
void* userdata;
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
void gai_fsm_init(gai_fsm_t* self, void* userdata){
|
||||
self->current_state_p = 0;
|
||||
os_list_init(&self->state_list);
|
||||
self->userdata = userdata;
|
||||
}
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
void gai_fsm_add_state(gai_fsm_t* self, gai_fsm_state_t * state){
|
||||
os_list_insert_after(&self->state_list, &state->node);
|
||||
}
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
void gai_fsm_add_transition(gai_fsm_t* self, gai_fsm_transition_t* transition){
|
||||
os_list_node_t* p_node;
|
||||
for(p_node = self->state_list.next; p_node!=&self->state_list; p_node = p_node->next){
|
||||
gai_fsm_state_t* p_state = os_list_member_of(p_node, gai_fsm_state_t, node);
|
||||
if(transition->from_state_id != p_state->id){
|
||||
continue;
|
||||
}
|
||||
os_list_insert_after(&p_state->transition_list, &transition->node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
gai_action_status_t gai_fsm_status(gai_fsm_t* self){
|
||||
if(self->current_state_p){
|
||||
return self->current_state_p->action.status;
|
||||
}
|
||||
return kGaiActionStatus_UnInitialized;
|
||||
}
|
||||
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
gai_fsm_transition_t* gai_fsm_find_transition(gai_fsm_t* self, os_int_t from_state_id, os_int_t to_state_id){
|
||||
gai_fsm_state_t * p_from_state = 0;
|
||||
os_list_node_t* p_node;
|
||||
for(p_node = self->state_list.next; p_node!=&self->state_list; p_node = p_node->next){
|
||||
gai_fsm_state_t* p_state = os_list_member_of(p_node, gai_fsm_state_t, node);
|
||||
if(p_state->id==from_state_id){
|
||||
p_from_state = p_state;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(p_from_state==0){
|
||||
return 0;
|
||||
}
|
||||
for(p_node = p_from_state->transition_list.next; p_node!=&p_from_state->transition_list; p_node= p_node->next){
|
||||
gai_fsm_transition_t* p_transition = os_list_member_of(p_node, gai_fsm_transition_t, node);
|
||||
if(p_transition->to_state_id == to_state_id){
|
||||
return p_transition;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
gai_fsm_state_t* gai_fsm_find_state(gai_fsm_t* self, os_int_t state_id){
|
||||
os_list_node_t* p_node;
|
||||
for(p_node = self->state_list.next; p_node!=&self->state_list; p_node = p_node->next){
|
||||
gai_fsm_state_t* p_state = os_list_member_of(p_node, gai_fsm_state_t, node);
|
||||
if(p_state->id==state_id){
|
||||
return p_state;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
os_bool_t gai_fsm_has_transition(gai_fsm_t* self, os_int_t from_state_id, os_int_t to_state_id){
|
||||
return (gai_fsm_find_transition(self, from_state_id, to_state_id)!=0)?OS_TRUE:OS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
os_bool_t gai_fsm_has_state(gai_fsm_t* self, os_int_t state_id){
|
||||
return (gai_fsm_find_state(self, state_id)!=0)?OS_TRUE:OS_FALSE;
|
||||
}
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
void gai_fsm_set_state(gai_fsm_t* self, os_int_t state_id){
|
||||
gai_fsm_state_t* p_state = gai_fsm_find_state(self, state_id);
|
||||
if(p_state==0){
|
||||
return;
|
||||
}
|
||||
gai_action_Cleanup(&p_state->action);
|
||||
self->current_state_p = p_state;
|
||||
gai_action_Initialize(&p_state->action);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
void gai_fsm_state_init(gai_fsm_state_t* self, os_int_t id,
|
||||
gai_action_function_t onInitialize,
|
||||
gai_action_update_function_t onUpdate,
|
||||
gai_action_function_t onCleanup, void* userdata){
|
||||
os_list_init(&self->node);
|
||||
self->id = id;
|
||||
os_list_init(&self->transition_list);
|
||||
gai_action_init(&self->action, onInitialize, onUpdate, onCleanup, userdata);
|
||||
}
|
||||
|
||||
OS_STATIC_FORCE_INLINE
|
||||
void gai_fsm_transition_init(gai_fsm_transition_t* self,
|
||||
os_int_t from_state_id,
|
||||
os_int_t to_state_id,
|
||||
gai_fsm_evaluator_t evaluator,
|
||||
void* userdata){
|
||||
self->evaluator = evaluator;
|
||||
self->from_state_id = from_state_id;
|
||||
self->to_state_id = to_state_id;
|
||||
os_list_init(&self->node);
|
||||
self->userdata = userdata;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
|
||||
void gai_fsm_update(gai_fsm_t* self, void* userdata);
|
||||
|
||||
#endif /*INCLUDED_GAI_FSM_H*/
|
||||
Reference in New Issue
Block a user