一、背景
以前写状态机的思路都是if else或者switch case,今天我们稍微把思路整理一下,把状态机的状态迁移,和事件触发管理的更直观一些。
二、正题
假设有3个状态,3个事件,每个事件都会触发状态机的状态迁移。在状态机处于某个状态时,都需要执行一次该状态的函数;在事件来临时,即状态发生迁移时,只需要执行一次
状态迁移函数。
StateTransform stateTran[] =
{
/*currState,event, nextState, func cycle, func trigger */
{state_1, event_3,state_3, func_s1_runing, NULL},
{state_2, event_3,state_3, func_s2_runing, func_s1_Tr_13},
{state_3, event_1,state_2, NULL, func_s3_Tr_s2},
};
表中分别是:当前状态,事件,下个状态,周期执行的函数(或空),执行一次的函数(或空)。
这里有3个状态,分别时state_1,2,3。有3个事件,分别是event_1,2,3。
例如处于state_2时,每次都执行func_s2_runing函数,当发生event_3事件时,状态要从2迁移到3,并且只会执行一次func_s1_Tr_13函数。
三、调度与执行
runStateMachine(&stateMachine, num);
num为事件,传入状态机引擎函数即可。
StateTransform* findTranss(StateMachine_T* pSM)
{
int i;
for (i = 0; i < pSM->transNum; i++)
{
if ((pSM->p_transform[i].curState == pSM->state))// && (pSM->p_transform[i].eventId == evt))
{
return &pSM->p_transform[i];
}
}
return NULL;
}
void runStateMachine(StateMachine_T* pSM, EventID evt)
{
StateTransform* pTrans;
pTrans = findTranss(pSM);
if (pTrans == NULL)
{
printf( "CurState= %d Do not process enent: %d\r\n", pSM->state,evt);
return;
}
printf("curState = %d;",pTrans->curState);
if(evt == pTrans->eventId)
{
printf("Event = %d\r\n",pTrans->eventId);
if (pTrans->CBTrigFunc != NULL)
{
pTrans->CBTrigFunc(&evt);
}
else
{
printf("triger func is NULL\r\n");
}
pSM->state = pTrans->nextState;
}
else
{
if (pTrans->CBfunc != NULL)
{
pTrans->CBfunc(&evt);
}
else
{
printf("running func is NULL\r\n");
}
}
}
执行过程很简单,根据当前的状态,去表里找到该状态,然后执行周期性的函数,此时如果有事件发生,那么就发生状态迁移,只执行迁移函数。
四、测试
-----------func_s1_Tr_13-----------
num = 0
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 1
curState = 3;Event = 1
-----------func_s3_Tr_s2-----------
num = 1
curState = 2;***********state 2 running***********
num = 0
curState = 2;***********state 2 running***********
num = 2
curState = 2;***********state 2 running***********
num = 3
curState = 2;Event = 3
-----------func_s1_Tr_13-----------
num = 2
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 1
curState = 3;Event = 1
-----------func_s3_Tr_s2-----------
num = 2
curState = 2;***********state 2 running***********
num = 1
curState = 2;***********state 2 running***********
num = 3
curState = 2;Event = 3
-----------func_s1_Tr_13-----------
num = 2
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 1
curState = 3;Event = 1
-----------func_s3_Tr_s2-----------
num = 0
curState = 2;***********state 2 running***********
num = 1
curState = 2;***********state 2 running***********
num = 2
curState = 2;***********state 2 running***********
num = 0
curState = 2;***********state 2 running***********
num = 2
curState = 2;***********state 2 running***********
num = 2
curState = 2;***********state 2 running***********
num = 0
curState = 2;***********state 2 running***********
num = 3
curState = 2;Event = 3
-----------func_s1_Tr_13-----------
num = 0
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 1
curState = 3;Event = 1
-----------func_s3_Tr_s2-----------
num = 3
curState = 2;Event = 3
-----------func_s1_Tr_13-----------
num = 2
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 0
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 0
curState = 3;running func is NULL
num = 0
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 0
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 0
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 0
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 1
curState = 3;Event = 1
-----------func_s3_Tr_s2-----------
num = 2
curState = 2;***********state 2 running***********
num = 2
curState = 2;***********state 2 running***********
num = 1
curState = 2;***********state 2 running***********
num = 2
curState = 2;***********state 2 running***********
num = 2
curState = 2;***********state 2 running***********
num = 0
curState = 2;***********state 2 running***********
num = 2
curState = 2;***********state 2 running***********
num = 2
curState = 2;***********state 2 running***********
num = 1
curState = 2;***********state 2 running***********
num = 1
curState = 2;***********state 2 running***********
num = 3
curState = 2;Event = 3
-----------func_s1_Tr_13-----------
num = 3
curState = 3;running func is NULL
num = 2
curState = 3;running func is NULL
num = 1
curState = 3;Event = 1
-----------func_s3_Tr_s2-----------
num = 0
curState = 2;***********state 2 running***********
num = 0
curState = 2;***********state 2 running***********
num = 3
curState = 2;Event = 3
-----------func_s1_Tr_13-----------
num = 3
curState = 3;running func is NULL
num = 0
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 0
curState = 3;running func is NULL
num = 0
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 3
curState = 3;running func is NULL
num = 0
curState = 3;running func is NULL
五、源代码