overview
Finite State Machine is kown as FSM
,it’s used when we need swith among diffrenet states,sometimes,we can use switch
statement,but it has some limitation when it comes to the Event-Based situation
what elements does the FSM basically need
first of most ,there are four concepts in FSM : arrived event
,current state
,Tacke Action
and next state
-
Arrived Event
we all know that FSM is used in diffrent states,so we need kown when to switch state ,it might happes when we input something by the keyboard or some function has been done, state is usually drived by the logical task.diffrenet task creates diffrenet event.so the time that state switched is determined by event
-
Current State
we have kown something will happen when a new event arrived, but do we have take action immidiately as soon as the event arrived and what action we should take.the key is
current state
only current state matches with specfic state do we tack specific action,for instance, if our friends come by and knock door,we can open the door if we are watching TV(means we are at convient state),whreas, let my friends wait for a second when we are in bathroom(means we are at busy state).
-
Tacke Action
action means task,we tacke difrrent actions at diffrent event and diffrent state
-
Next State
when the action or task has been finished then we move on next state
Data Structure
according to the element which a FSM need,we can create a basic stucture as below
typedef struct {
int event; //incomming event
int CurState; //current state
void (ImFile::*eventActFun)(); //task
int NextState; //next state
}CF_StateTable;
now we already have a structure of FSM, as we mentioned before,the state will be swith at diffrent situation,so how the code kown and run normally and orderly .there should be a rule or a table the code can be abide by. as soon as the event arrive,we can only look up the state table,do something by the rule
CF_StateTable fTable[13]={
//{到来的事件,当前的状态,将要要执行的函数,下一个状态}
{ E_INIT, S_IDLE, &ImFile::Init, S_INIT },
{ E_INIT, S_STOPPED, &ImFile::Init, S_INIT },
{ E_START, S_INIT, &ImFile::Start, S_RUNNING },
{ E_START, S_RUNNING, &ImFile::Start, S_RUNNING },
{ E_START, S_STOPPED, &ImFile::Init, S_INIT},
{ E_PAUSE, S_RUNNING, &ImFile::Resume, S_RESUM},
{ E_PAUSE, S_RESUM, &ImFile::Resume, S_RESUM},
{ E_RESUME, S_RESUM, &ImFile::Start, S_RUNNING},
{ E_RESUME, S_RUNNING, &ImFile::Start, S_RUNNING},
{ E_RESUME, S_INIT, &ImFile::Start, S_RUNNING},
{ E_STOP, S_RUNNING, &ImFile::Stop, S_STOPPED },
{ E_STOP, S_RESUM, &ImFile::Stop, S_STOPPED },
{ E_STOP, S_INIT, &ImFile::Stop, S_STOPPED }
//add your code here
};
as you see,we create a statetable which record every rules,for example, in this rule
{ E_PAUSE, S_RUNNING, &ImFile::Resume, S_RESUM},
if there are E_PAUSE
event created and current state is also S_RUNNIG
,then we excute Resum function ,after that ,we change the current state to S_RESUM
. then we will look up the tale utill next arrived event arrived.
sometimes ,there are many FSM not only one ,so we define a stucture to refer to the type of FSM
/** 状态机类型*/
typedef struct {
int curState;//当前状态
CF_StateTable * stateTable;//状态表
int size;//表的项数
}CF_FsmType;
HOW does FSM run
now,all base coverd,it time to warm up our machine and get it run.
-
regist a FSM
we can create many FSM we mention before,but put it simple,we only create one FSM and regist
CF_FsmType pType; pType.stateTable =fTable;//register a statetable pType.curState = S_IDLE;//set original state pType.size = sizeof(fTable)/sizeof(CF_StateTable);
-
Traverse StateTable
、TakeAction
、Transfer State
void ImFile::fsmEventHandle() { int event; if(!IsEventListEmpty()){ event = GetOneEvent(); CF_StateTable* pActTable =pType.stateTable; void (ImFile::*eventActFun)() = NULL; //函数指针初始化为空 int NextState; int CurState = pType.curState; int maxNum = pType.size; int flag = 0; //标识是否满足条件 //PrintEventState(LOG_DEBUG,event,CurState); /*获取当前动作函数*/ for (int i = 0; i<maxNum; i++)//Traverse StateTable { //当且仅当当前状态下来个指定的事件,我才执行它 if (event == pActTable[i].event && CurState == pActTable[i].CurState) { flag = 1; eventActFun = pActTable[i].eventActFun; NextState = pActTable[i].NextState; break; } } if (flag) //如果满足条件了 { /*动作执行*/ if (eventActFun) { (this->*eventActFun)(); //take action } //跳转到下一个状态 pType.curState=NextState; // Transfer State } else { LOG_MSG("ImFile",LOG_ERROR,"there is no match"); PrintEventState(LOG_ERROR, event, CurState); } }else{ LOG_MSG("ImFile",LOG_ERROR,"there is no any event"); std::this_thread::sleep_for(std::chrono::seconds(5)); //std::cout<<"there is no any event"<<std::endl; } }