mirror of
https://gitee.com/zlgopen/awtk.git
synced 2024-12-02 03:58:33 +08:00
add state_machine
This commit is contained in:
parent
6661c0bb70
commit
1fc25f4ed2
@ -3,6 +3,7 @@
|
||||
2021/12/24
|
||||
* 修复mingw编译说明文档(感谢智明提供补丁)
|
||||
* 修复SDL释放的时候内存泄露的问题(感谢智明提供补丁)
|
||||
* 增加状态机(感谢林福提供补丁)
|
||||
|
||||
2021/12/23
|
||||
* 增加aworkslp平台支持(感谢林福提供补丁)
|
||||
|
145
src/tkc/state_machine.c
Normal file
145
src/tkc/state_machine.c
Normal file
@ -0,0 +1,145 @@
|
||||
/**
|
||||
* File: state_machine.c
|
||||
* Author: AWTK Develop Team
|
||||
* Brief: state_machine
|
||||
*
|
||||
* Copyright (c) 2019 - 2019 Guangzhou ZHIYUAN Electronics Co.,Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* History:
|
||||
* ================================================================
|
||||
* 2020-12-29 code generated
|
||||
* 2020-12-29 Wang LinFu <wanglinfu@zlg.cn> created
|
||||
*
|
||||
*/
|
||||
#include "state_machine.h"
|
||||
#include "tkc/mem.h"
|
||||
|
||||
static tk_sm_transition_t* tk_state_machine_get_transition(tk_state_machine_t* fsm,
|
||||
tk_sm_event_t* const event,
|
||||
bool_t* is_back) {
|
||||
const tk_sm_state_t* state = fsm->current_state;
|
||||
size_t i;
|
||||
|
||||
*is_back = FALSE;
|
||||
for (i = 0; i < state->ntransitions; ++i) {
|
||||
tk_sm_transition_t* t = &state->transitions[i];
|
||||
|
||||
/* A transition for the given event has been found: */
|
||||
if (t->etype == event->type) {
|
||||
if (!t->guard) return t;
|
||||
/* If transition is guarded, ensure that the condition is held: */
|
||||
else if (t->guard(t->condition, event))
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < state->ntransitions_back; ++i) {
|
||||
tk_sm_transition_t* t = &state->transitions_back[i];
|
||||
|
||||
/* A transition for the given event has been found: */
|
||||
if (t->etype == event->type) {
|
||||
if (!t->guard) {
|
||||
*is_back = TRUE;
|
||||
return t;
|
||||
}
|
||||
/* If transition is guarded, ensure that the condition is held: */
|
||||
else if (t->guard(t->condition, event)) {
|
||||
*is_back = TRUE;
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (state->base_state) {
|
||||
state = state->base_state;
|
||||
return_value_if_fail(state->transitions && state->ntransitions, NULL);
|
||||
for (i = 0; i < state->ntransitions; ++i) {
|
||||
tk_sm_transition_t* t = &state->transitions[i];
|
||||
if (!t->next_state) {
|
||||
t->next_state = state;
|
||||
}
|
||||
/* A transition for the given event has been found: */
|
||||
if (t->etype == event->type) {
|
||||
if (!t->guard) return t;
|
||||
/* If transition is guarded, ensure that the condition is held: */
|
||||
else if (t->guard(t->condition, event))
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No transitions found for given event for given state: */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret_t tk_state_machine_init(tk_state_machine_t* fsm, const tk_sm_state_t* initial_state) {
|
||||
return_value_if_fail(fsm, RET_BAD_PARAMS);
|
||||
return_value_if_fail(initial_state, RET_BAD_PARAMS);
|
||||
|
||||
/* 初始状态不允许有 transitions_back ,防止无限递归 */
|
||||
return_value_if_fail(initial_state->ntransitions_back == 0, RET_BAD_PARAMS);
|
||||
return_value_if_fail(initial_state->transitions_back == NULL, RET_BAD_PARAMS);
|
||||
|
||||
fsm->current_state = initial_state;
|
||||
fsm->previous_state = NULL;
|
||||
return RET_OK;
|
||||
}
|
||||
|
||||
ret_t tk_state_machine_handle(tk_state_machine_t* fsm, tk_sm_event_t* event) {
|
||||
return_value_if_fail(fsm && event, RET_BAD_PARAMS);
|
||||
return_value_if_fail(fsm->current_state, RET_NOT_IMPL);
|
||||
|
||||
const tk_sm_state_t* next_state;
|
||||
bool_t is_back;
|
||||
tk_sm_transition_t* transition = tk_state_machine_get_transition(fsm, event, &is_back);
|
||||
return_value_if_fail(transition, RET_NOT_FOUND);
|
||||
|
||||
if (transition->next_state) {
|
||||
next_state = transition->next_state;
|
||||
} else {
|
||||
next_state = fsm->current_state;
|
||||
}
|
||||
|
||||
if (next_state != fsm->current_state && fsm->current_state->exit_action) {
|
||||
fsm->current_state->exit_action(fsm->current_state->data, event);
|
||||
}
|
||||
|
||||
/* action 在 exit 之后,如果要在 exit 之前执行的操作,可以放在 guard 中 */
|
||||
if (transition->action) {
|
||||
transition->action(fsm->current_state->data, event, next_state->data);
|
||||
}
|
||||
if (!is_back) {
|
||||
if (next_state != fsm->current_state && next_state->entry_action) {
|
||||
next_state->entry_action(next_state->data, event);
|
||||
}
|
||||
fsm->previous_state = fsm->current_state;
|
||||
fsm->current_state = next_state;
|
||||
return RET_OK;
|
||||
} else {
|
||||
return_value_if_fail(next_state != fsm->current_state, RET_FAIL);
|
||||
fsm->previous_state = fsm->current_state;
|
||||
fsm->current_state = next_state;
|
||||
return tk_state_machine_handle(fsm, event);
|
||||
}
|
||||
}
|
||||
|
||||
const tk_sm_state_t* tk_state_machine_current_get(tk_state_machine_t* fsm) {
|
||||
return_value_if_fail(fsm, NULL);
|
||||
return fsm->current_state;
|
||||
}
|
||||
|
||||
const tk_sm_state_t* tk_state_machine_previous_get(tk_state_machine_t* fsm) {
|
||||
return_value_if_fail(fsm, NULL);
|
||||
return fsm->previous_state;
|
||||
}
|
||||
|
||||
ret_t tk_state_machine_deinit(tk_state_machine_t* fsm, tk_sm_event_t* event) {
|
||||
return_value_if_fail(fsm, RET_BAD_PARAMS);
|
||||
if (fsm->current_state->exit_action) {
|
||||
fsm->current_state->exit_action(fsm->current_state->data, event);
|
||||
}
|
||||
memset(fsm, 0, sizeof(*fsm));
|
||||
return RET_OK;
|
||||
}
|
123
src/tkc/state_machine.h
Normal file
123
src/tkc/state_machine.h
Normal file
@ -0,0 +1,123 @@
|
||||
/**
|
||||
* File: state_machine.h
|
||||
* Author: AWTK Develop Team
|
||||
* Brief: state_machine
|
||||
*
|
||||
* Copyright (c) 2019 - 2021 Guangzhou ZHIYUAN Electronics Co.,Ltd.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* History:
|
||||
* ================================================================
|
||||
* 2020-12-29 Wang LinFu <wanglinfu@zlg.cn> 修改自 https://github.com/misje/stateMachine.git
|
||||
*
|
||||
*/
|
||||
#ifndef TK_STATE_MACHINE_H
|
||||
#define TK_STATE_MACHINE_H
|
||||
|
||||
#include "tkc/types_def.h"
|
||||
|
||||
BEGIN_C_DECLS
|
||||
|
||||
typedef struct _tk_sm_state_t tk_sm_state_t;
|
||||
typedef struct _tk_sm_event_t tk_sm_event_t;
|
||||
|
||||
/**
|
||||
* @class tk_sm_event_t
|
||||
* 状态机事件
|
||||
*/
|
||||
struct _tk_sm_event_t {
|
||||
int type;
|
||||
void* data;
|
||||
};
|
||||
|
||||
/**
|
||||
* @class tk_sm_transition_t
|
||||
* 状态转换条件
|
||||
*/
|
||||
typedef struct {
|
||||
int etype;
|
||||
void* condition;
|
||||
bool_t (*guard)(void* condition, tk_sm_event_t* event);
|
||||
void (*action)(void* current_stat_data, tk_sm_event_t* event, void* new_state_data);
|
||||
const tk_sm_state_t* next_state;
|
||||
} tk_sm_transition_t;
|
||||
|
||||
/**
|
||||
* @class tk_sm_state_t
|
||||
* 状态结构体
|
||||
*/
|
||||
struct _tk_sm_state_t {
|
||||
const tk_sm_state_t* base_state;
|
||||
tk_sm_transition_t* transitions;
|
||||
size_t ntransitions;
|
||||
tk_sm_transition_t* transitions_back;
|
||||
size_t ntransitions_back;
|
||||
void* data;
|
||||
void (*entry_action)(void* state_data, tk_sm_event_t* event);
|
||||
void (*exit_action)(void* state_data, tk_sm_event_t* event);
|
||||
};
|
||||
|
||||
/**
|
||||
* @class tk_state_machine_t
|
||||
* 状态机结构体
|
||||
*/
|
||||
typedef struct {
|
||||
const tk_sm_state_t* current_state;
|
||||
const tk_sm_state_t* previous_state;
|
||||
} tk_state_machine_t;
|
||||
|
||||
/**
|
||||
* @method tk_state_machine_init
|
||||
* 初始化
|
||||
*
|
||||
* @param {tk_state_machine_t*} fsm 状态机地址
|
||||
* @param {const tk_sm_state_t*} initial_state 初始状态
|
||||
*
|
||||
* @return {ret_t} 返回 ret_t 值
|
||||
*/
|
||||
ret_t tk_state_machine_init(tk_state_machine_t* fsm, const tk_sm_state_t* initial_state);
|
||||
|
||||
/**
|
||||
* @method tk_state_machine_handle
|
||||
* 事件处理
|
||||
*
|
||||
* @param {tk_state_machine_t*} fsm 状态机地址
|
||||
* @param {tk_sm_event_t*} event 事件
|
||||
*
|
||||
* @return {ret_t} 返回 ret_t 值
|
||||
*/
|
||||
ret_t tk_state_machine_handle(tk_state_machine_t* fsm, tk_sm_event_t* event);
|
||||
/**
|
||||
* @method tk_state_machine_previous_get
|
||||
* 获取上一个状态
|
||||
*
|
||||
* @param {tk_state_machine_t*} fsm 状态机地址
|
||||
*
|
||||
* @return {tk_sm_state_t*} 返回 tk_sm_state_t 对象
|
||||
*/
|
||||
const tk_sm_state_t* tk_state_machine_previous_get(tk_state_machine_t* fsm);
|
||||
/**
|
||||
* @method tk_state_machine_current_get
|
||||
* 获取当前状态
|
||||
*
|
||||
* @param {tk_state_machine_t*} fsm 状态机地址
|
||||
*
|
||||
* @return {tk_sm_state_t*} 返回 tk_sm_state_t 对象
|
||||
*/
|
||||
const tk_sm_state_t* tk_state_machine_current_get(tk_state_machine_t* fsm);
|
||||
/**
|
||||
* @method tk_state_machine_deinit
|
||||
* 反初始化
|
||||
*
|
||||
* @param {tk_state_machine_t*} fsm 状态机地址
|
||||
* @param {tk_sm_event_t*} event 事件
|
||||
*
|
||||
* @return {ret_t} 返回 ret_t 值
|
||||
*/
|
||||
ret_t tk_state_machine_deinit(tk_state_machine_t* fsm, tk_sm_event_t* event);
|
||||
|
||||
END_C_DECLS
|
||||
|
||||
#endif /*TK_STATE_MACHINE_H*/
|
8
tests/state_machine_test.cc
Normal file
8
tests/state_machine_test.cc
Normal file
@ -0,0 +1,8 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
extern "C"
|
||||
void state_machine_utest(void);
|
||||
|
||||
TEST(StateMachine, utest) {
|
||||
state_machine_utest();
|
||||
}
|
Loading…
Reference in New Issue
Block a user