FSM Implementation 状态机实现

Posted tangtangworld

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FSM Implementation 状态机实现相关的知识,希望对你有一定的参考价值。

 

第一次写状态机,参考现有代码写了一个框架,在网上看了一些例子,结果就陷入了纠结中,不知道状态机哪种形式比较好,是不是还缺少什么,各位大牛有什么建议敬请回复,我会持续更新,非常感谢!

 

第一种形式: 所有的状态通过if...else来跳转,主线程收到消息之后会进入当前状态进行处理,在一大堆的if...else里面理出整个状态的迁移过程比较痛苦;

第二种形式: 通过switch...case,等价于if...else,(个人理解switch...case就是if...else的优雅写法);

第三种形式: 所有状态维护在一个列表中,外部事件处理与状态切换统一处理,比较容易分析;

 

代码比较简单,而且只有百行,没有写注释,请大家见谅,实现的状态切换如下:

IDLE-------EventX---->StateA

StateA-----EventY---->StateB;

StateA-----EventX---->IDLE;

 

  1 #include <stdio.h>
  2 #include <assert.h>
  3 
  4 #define MAX_STATE_NAME_LEN (32)
  5 
  6 enum ErrorCode
  7 {
  8     EOK       = 0,
  9     EBADVALUE = -1,
 10 };
 11 
 12 typedef enum Event
 13 {
 14     Event_X  = 1,
 15     Event_Y  = 2,
 16     Event_Z  = 3,
 17 }Event;
 18 
 19 typedef enum State
 20 {
 21     STATE_IDLE    = 0x0,
 22     STATE_A       = 0x1,
 23     STATE_B       = 2,
 24     STATE_INVALID = 3,
 25 }State;
 26 
 27 struct FsmContext;
 28 typedef int  (*fsm_handler)(struct FsmContext *pctxt, Event, void *data);
 29 
 30 struct FsmTable
 31 {
 32     State curState;
 33     Event evt;
 34     State nextState;
 35     char curStateName[MAX_STATE_NAME_LEN];
 36     fsm_handler handler;
 37 };
 38 
 39 struct FsmContext
 40 {
 41     State curState;
 42     State prevState;
 43     struct FsmTable *pfsmTable;
 44 };
 45 
 46 int fsm_handler_state_idle(struct FsmContext *pctxt, Event, void *data);
 47 int fsm_handler_state_a(struct FsmContext *pctxt, Event, void *data);
 48 int fsm_handler_state_b(struct FsmContext *pctxt, Event, void *data);
 49 
 50 struct FsmTable fsmTable[] = 
 51 {
 52     /*CurState      Event       NextState   CurStateName    Handler*/
 53     {STATE_IDLE,    Event_X,    STATE_A,    "STATE_IDLE",   fsm_handler_state_idle},
 54     {STATE_A,       Event_Y,    STATE_B,    "STATE_A",      fsm_handler_state_a},
 55     {STATE_A,       Event_X,    STATE_IDLE, "STATE_A",      fsm_handler_state_a},
 56     {STATE_B,       Event_Z,    STATE_A,    "STATE_B",      fsm_handler_state_b},
 57 };
 58 
 59 struct FsmTable *g_pTable = fsmTable;
 60 struct FsmContext ctxt;
 61 struct FsmContext *g_pCtxt = &ctxt;
 62 
 63 int fsm_init(struct FsmTable *ptable, struct FsmContext *pctxt)
 64 {
 65     assert(ptable);
 66     assert(pctxt);
 67 
 68     pctxt->curState = STATE_IDLE;
 69     pctxt->prevState = STATE_INVALID;
 70     pctxt->pfsmTable = ptable;
 71 
 72     return EOK;
 73 }
 74 
 75 int fsm_state_transfer(struct FsmTable *ptable, struct FsmContext *pctxt, State nextState)
 76 {
 77     assert(ptable);
 78     assert(pctxt);
 79     pctxt->prevState = pctxt->curState;
 80     pctxt->curState = nextState;
 81     return EOK;
 82 }
 83 
 84 struct FsmTable * fsm_get_handler(struct FsmTable *ptable, State curState, Event evt)
 85 {
 86     assert(ptable);
 87     struct FsmTable *p = ptable;
 88     int i = 0x0;
 89     int num = sizeof(fsmTable)/sizeof(fsmTable[0]);
 90 
 91     for(i = 0x0; i < num; i++)
 92     {
 93         if(NULL != p && p->curState == curState && p->evt == evt)
 94         {
 95             return p;
 96         }
 97         p++;
 98     }
 99     return NULL;
100 }
101 
102 int fsm_evt_handler(struct FsmTable *ptable, struct FsmContext *pctxt, Event evt, void *data)
103 {
104     assert(ptable);
105     assert(pctxt);
106     assert(data);
107     struct FsmTable *p = NULL;
108     
109     p = fsm_get_handler(ptable, pctxt->curState, evt);
110     
111     if(NULL != p)
112     {
113         if(NULL != p->handler)
114         {
115             p->handler(pctxt, evt, data);
116         }
117         fsm_state_transfer(ptable, pctxt, p->nextState);
118     }
119     else
120     {
121         return EBADVALUE;
122     }
123 
124     return EOK;
125 }
126 
127 int fsm_handler_state_idle(struct FsmContext *pctxt, Event evt, void *data)
128 {
129     assert(pctxt);
130     assert(data);
131     printf("prev state:%d, cur state:%d, evt:%d, data:%s\n",  pctxt->prevState, pctxt->curState, evt, (char*)data);
132     return EOK;
133 }
134 
135 int fsm_handler_state_a(struct FsmContext *pctxt, Event evt, void *data)
136 {
137     assert(pctxt);
138     assert(data);
139     printf("prev state:%d, cur state:%d, evt:%d, data:%s\n",  pctxt->prevState, pctxt->curState, evt, (char*)data);
140     return EOK;
141 }
142 
143 int fsm_handler_state_b(struct FsmContext *pctxt, Event evt, void *data)
144 {
145     assert(pctxt);
146     assert(data);
147     printf("prev state:%d, cur state:%d, evt:%d, data:%s\n",  pctxt->prevState, pctxt->curState, evt, (char*)data);
148     return EOK;
149 }
150 
151 int main(void)
152 {
153     fsm_init(g_pTable, g_pCtxt);
154     Event evt = Event_X;
155     char *data = "hello world";
156 
157     fsm_evt_handler(g_pTable, g_pCtxt, Event_X, (void*)data);
158     fsm_evt_handler(g_pTable, g_pCtxt, Event_X, (void*)data);
159     fsm_evt_handler(g_pTable, g_pCtxt, Event_X, (void*)data);
160     fsm_evt_handler(g_pTable, g_pCtxt, Event_Y, (void*)data);
161     fsm_evt_handler(g_pTable, g_pCtxt, Event_Z, (void*)data);
162 
163     return EOK;
164 }

 

以上是关于FSM Implementation 状态机实现的主要内容,如果未能解决你的问题,请参考以下文章

状态机FSM

FSM有限状态机的实现

Unity中的AI算法和实现2-有限状态机FSM(上)

利用简单的有限状态机(FSM)来实现一个简单的LED流水灯

有限状态机FSM(Finite State Machine)及实现方式介绍

有限状态机FSM(Finite State Machine)及实现方式介绍