Files
RTOS/AppKit/gai_fsm.h
T
2026-06-05 23:18:54 +08:00

181 lines
5.5 KiB
C

#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*/