3 minute read

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.

  1. 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);
    
  2. Traverse StateTableTakeActionTransfer 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;
         }
       
    }
    

Updated: