作者:CppExplore 網(wǎng)址:http://www.shnenglu.com/CppExplore/
上接《系統(tǒng)設(shè)計(jì)之 狀態(tài)機(jī)(一)》
三、狀態(tài)機(jī)實(shí)現(xiàn)
(2)面向過程方式
2、層次狀態(tài)機(jī)模塊實(shí)現(xiàn)。
與常規(guī)狀態(tài)機(jī)相比,它的FSM_STATE結(jié)構(gòu)沒有default_func,多了 FSM_STATE_ID parent; FSM_STATE_ID default_child;兩個(gè)結(jié)構(gòu)。狀態(tài)機(jī)初始化的時(shí)候可以指定默認(rèn)狀態(tài),為了防止指定的狀態(tài)非葉結(jié)點(diǎn),增加fsm_init方法。該狀態(tài)機(jī)的事件處理算法簡(jiǎn)單描述如下:(1)首先在當(dāng)前狀態(tài)以及其祖先狀態(tài)的狀態(tài)事件表中搜索匹配事件,如果搜索到,保存操作以及目的狀態(tài)標(biāo)識(shí);(2)在old棧中保存當(dāng)前狀態(tài)到根節(jié)點(diǎn)的路徑,在new棧中保存目的狀態(tài)到根節(jié)點(diǎn)的路徑;(3)將old棧中的頂層元素依次與new棧的頂層元素匹配,如果匹配則都出棧,不匹配,停止;(4)當(dāng)前的old棧中節(jié)點(diǎn)即為該事件導(dǎo)致的退出狀態(tài),從棧低掃描到棧頂,依次執(zhí)行exit_func;(5)執(zhí)行以前保存的操作;(6)掃描new棧,從棧頂?shù)綏5鸵来螆?zhí)行enter_func;(7)最后檢測(cè)目的狀態(tài)是否是葉節(jié)點(diǎn)狀態(tài),否,則依次進(jìn)入default_child節(jié)點(diǎn),并執(zhí)行enter_func。模塊實(shí)現(xiàn)代碼如下:
#define SINGLE_STATE_MAX_EVENT 10
#define STATE_TREE_DEPTH 10
typedef int FSM_EVENT_ID;
typedef struct event_param_st


{
FSM_EVENT_ID id;

union
{
int i;
}data;
}FSM_EVENT;
typedef int FSM_STATE_ID;
typedef void (*FSM_FUNC)(FSM_EVENT *);
typedef struct state_event_st


{
FSM_FUNC func;
FSM_EVENT_ID event;
FSM_STATE_ID state;
}FSM_STATE_EVENT;
typedef struct state_st


{
FSM_STATE_ID id;
char *name;
FSM_STATE_ID parent;
FSM_STATE_ID default_child;
FSM_FUNC enter_func;
FSM_FUNC exit_func;
FSM_STATE_EVENT event_table[SINGLE_STATE_MAX_EVENT];
}FSM_STATE;
typedef FSM_STATE STATE_TABLE[];
typedef FSM_STATE * PTR_STATE_TABLE;

#define END_EVENT_ID -1
#define END_STATE_ID -1

#define BEGIN_FSM_STATE_TABLE(state_stable) static STATE_TABLE state_stable=
{

#define BEGIN_STATE(id,name,parent,default_child,enter_func,exit_func)
{id,name,parent,default_child,enter_func,exit_func,
{

#define STATE_EVENT_ITEM(func,event,state)
{func,event,state},

#define END_STATE(id)
{NULL,END_EVENT_ID,END_STATE_ID}}},

#define END_FSM_STATE_TABLE(state_stable)
{END_STATE_ID,NULL,END_STATE_ID,END_STATE_ID,NULL,NULL,NULL}};

typedef struct fsm_st


{
FSM_STATE_ID state_id;
FSM_FUNC default_func;
PTR_STATE_TABLE state_tables;
}FSM;

void fsm_init(FSM &fsm)


{
FSM_STATE *state=&(fsm.state_tables[fsm.state_id]);
while(state->default_child!=END_STATE_ID)

{
state=&(fsm.state_tables[state->default_child]);
if(state->enter_func)
state->enter_func(NULL);
}
fsm.state_id=state->id;
}
void fsm_do_event(FSM &fsm, FSM_EVENT &event)


{
FSM_STATE *state;
FSM_STATE_ID state_id,old_state_id,new_state_id;
FSM_STATE_ID oldStack[STATE_TREE_DEPTH],newStack[STATE_TREE_DEPTH];
int old_cur=0,new_cur=0;
bool isMatch=false;
FSM_FUNC match_func=NULL;
int i=0;
state_id=old_state_id=fsm.state_id;
do

{
i=0;
state=&(fsm.state_tables[state_id]);
while(state->event_table[i].event!=END_EVENT_ID)

{
if(state->event_table[i].event==event.id)

{
isMatch=true;
match_func=state->event_table[i].func;
new_state_id=state->event_table[i].state;
break;
}
i++;
}
if(isMatch==false)
state_id=state->parent;
else
break;
}while(state->parent!=END_STATE_ID);
if(isMatch==false)

{
if(fsm.default_func)
fsm.default_func(&event);
return;
}
if(new_state_id==old_state_id)

{
if(match_func)
match_func(&event);
return;
}
state_id=old_state_id;
do

{
oldStack[old_cur++]=state_id;
state=&(fsm.state_tables[state_id]);
state_id=state->parent;
}while(state->parent!=END_STATE_ID);
state_id=new_state_id;
do

{
newStack[new_cur++]=state_id;
state=&(fsm.state_tables[state_id]);
state_id=state->parent;
}while(state->parent!=END_STATE_ID);
while(oldStack[old_cur-1]==newStack[new_cur-1])

{
old_cur--;
new_cur--;
}
for(i=0;i<old_cur;i++)

{
if(fsm.state_tables[oldStack[i]].exit_func)
fsm.state_tables[oldStack[i]].exit_func(&event);
}
if(match_func)
match_func(&event);
for(i=new_cur;i>0;i--)

{
if(fsm.state_tables[newStack[i-1]].enter_func)
fsm.state_tables[newStack[i-1]].enter_func(&event);
}
state=&(fsm.state_tables[new_state_id]);
while(state->default_child!=END_STATE_ID)

{
state=&(fsm.state_tables[state->default_child]);
if(state->enter_func)
state->enter_func(&event);
}
fsm.state_id=state->id;
}
使用舉例,僅僅列舉一個(gè)狀態(tài)表和簡(jiǎn)單的狀態(tài)機(jī)初始化,狀態(tài)和事件應(yīng)該為enum,當(dāng)前使用數(shù)字,僅為了舉例,操作的實(shí)現(xiàn)不在寫出。
BEGIN_FSM_STATE_TABLE(my_state_table)
BEGIN_STATE(0,"first",END_STATE_ID,2,enter_fsm,exit_fsm)
STATE_EVENT_ITEM(func_fsm,1,1)
STATE_EVENT_ITEM(func_fsm,2,2)
END_STATE(0)
BEGIN_STATE(1,"second",0,END_STATE_ID,enter_fsm,exit_fsm)
STATE_EVENT_ITEM(func_fsm,1,3)
STATE_EVENT_ITEM(func_fsm,2,0)
END_STATE(1)
BEGIN_STATE(2,"third",0,3,enter_fsm,exit_fsm)
STATE_EVENT_ITEM(func_fsm,1,0)
STATE_EVENT_ITEM(func_fsm,2,1)
END_STATE(2)
BEGIN_STATE(3,"third",2,END_STATE_ID,enter_fsm,exit_fsm)
STATE_EVENT_ITEM(func_fsm,1,4)
STATE_EVENT_ITEM(func_fsm,2,1)
END_STATE(3)
BEGIN_STATE(4,"third",2,END_STATE_ID,enter_fsm,exit_fsm)
STATE_EVENT_ITEM(func_fsm,1,2)
STATE_EVENT_ITEM(func_fsm,2,1)
END_STATE(4)
END_FSM_STATE_TABLE(my_state_table)

FSM fsm=
{0,default_fsm,my_state_table};
fsm_init(fsm);
FSM_EVENT event;
event.id=1;
event.data.i=1;
fsm_do_event(fsm,event);
后續(xù)提綱:
三、狀態(tài)機(jī)實(shí)現(xiàn)
(3)面向?qū)ο蠓绞?常規(guī)&層次
四、狀態(tài)機(jī)分析
五、狀態(tài)機(jī)回路檢測(cè)
六、狀態(tài)機(jī)使用
另介紹boost中同步異步狀態(tài)機(jī)