使用示例如下:
#include <stdio.h>
#include <unistd.h>
#include "simple_server.hpp"
using namespace SimpleServerFrame;
extern "C" {
StateFSM fsm;
enum TestState{
s_INIT = 0,
s_STATE_1 = 1,
s_STATE_2 = 2,
s_END = 3,
s_ERR = 4,
};
enum TestEvent{
e_EVENT_1 = 100,
e_EVENT_2 = 101,
e_EVENT_3 = 102,
e_EVENT_NOT_EXIST = 103,
};
enum TestAction{
a_ACTION_1 = 200,
a_ACTION_2 = 201,
a_ACTION_3 = 202,
a_ACTION_END = 203,
a_ACTION_ERROR = 204,
};
class Test:public IFsmCallback{
public:
int FsmCallback(int actionID){
switch(actionID){
case a_ACTION_1:
printf("s_INIT -> s_STATE_1\n");
fsm.PushEvent(e_EVENT_2);
break;
case a_ACTION_2:
printf("s_INIT -> s_STATE_2\n");
break;
case a_ACTION_3:
printf("s_STATE_1 -> s_STATE_2\n");
fsm.PushEvent(e_EVENT_3);
break;
case a_ACTION_END:
printf("s_STATE_2 -> s_END\n");
break;
case a_ACTION_ERROR:
printf("s_STATE_2 -> s_STATE_1 not allowed!\n");
break;
default:
printf("invalid action id\n");
break;
}
return 0;
}
};
// one time
int init()
{
// ...
fsm.AddFsmConfig(s_INIT, e_EVENT_1, s_STATE_1, a_ACTION_1);
fsm.AddFsmConfig(s_INIT, e_EVENT_2, s_STATE_2, a_ACTION_2);
fsm.AddFsmConfig(s_STATE_1, e_EVENT_2, s_STATE_2, a_ACTION_3);
fsm.AddFsmConfig(s_STATE_2, e_EVENT_1, s_ERR, a_ACTION_ERROR);
fsm.AddFsmConfig(s_STATE_2, e_EVENT_3, s_END, a_ACTION_END);
}
// each request
sResponse doJob(sRequest req)
{
Test *tt = new Test();
fsm.StartFsm(s_INIT, tt);
fsm.RunFsm(e_EVENT_1, tt);
sleep(1);
sResponse res;
res.iResId = req.iReqId;
return res;
}
}
FSM源码如下:
#ifndef __STATE_FSM_HPP__
#define __STATE_FSM_HPP__
#include <vector>
#include <map>
#include <queue>
namespace SimpleServerFrame{
using std::queue;
using std::vector;
using std::map;
typedef struct _fsmTransition{
int eventID;
int nextState;
int actionID;
}fsmTransition;
typedef struct _fsmState{
vector<fsmTransition> vecTransition;
}fsmState;
class IFsmCallback{
public:
virtual int FsmCallback(int actionID) = 0;
int FsmGetCurState(){
return _curState;
}
void FsmSetCurState(int curState){
_curState = curState;
}
private:
int _curState;
};
class StateFSM{
public:
StateFSM();
virtual ~StateFSM();
int StartFsm(int stateID, IFsmCallback *fsmobj);
int AddFsmConfig(int curState, int eventID, int nextState, int actionID);
int RunFsm(int eventID, IFsmCallback *fsmobj);
int PushEvent(int eventID);
private:
int doFsmEvent(int eventID, IFsmCallback *fsmobj);
int getActionID(int curState, int eventID, int &nextState, int &actionID);
private:
map<int, fsmState> mapState;
queue<int> queueEvent;
};
}
#endif
#include "state_fsm.hpp"
using namespace SimpleServerFrame;
using std::pair;
StateFSM::StateFSM()
{
mapState.clear();
}
StateFSM::~StateFSM()
{
}
int StateFSM::StartFsm(int stateID, IFsmCallback *fsmobj)
{
map<int, fsmState>::iterator stateIter;
stateIter = mapState.find(stateID);
if(stateIter != mapState.end())
{
fsmState state = stateIter->second;
if(state.vecTransition.size() == 0){
return -2; // only one state
}
}
else{
return -1; // no such state
}
fsmobj->FsmSetCurState(stateID);
}
int StateFSM::AddFsmConfig(int curState, int eventID, int nextState, int actionID)
{
fsmTransition transition;
transition.eventID = eventID;
transition.nextState = nextState;
transition.actionID = actionID;
map<int, fsmState>::iterator stateIter;
stateIter = mapState.find(curState);
if(stateIter != mapState.end()) {
stateIter->second.vecTransition.push_back(transition);
}
else{
fsmState state;
state.vecTransition.push_back(transition);
mapState.insert ( pair <int, fsmState> ( curState, state ) );
}
for(stateIter = mapState.begin(); stateIter!= mapState.end(); stateIter ++){
fsmState state = stateIter->second;
for(int i = 0 ; i < state.vecTransition.size();i ++){
transition = state.vecTransition[i];
}
}
}
int StateFSM::PushEvent(int eventID)
{
queueEvent.push(eventID);
}
int StateFSM::doFsmEvent(int eventID, IFsmCallback *fsmobj)
{
int curState = fsmobj->FsmGetCurState();
int actionID;
int nextState;
int iRet = getActionID(curState, eventID, nextState, actionID);
if(iRet == 0){
fsmobj->FsmSetCurState(nextState);
fsmobj->FsmCallback(actionID);
}
return 0;
}
int StateFSM::RunFsm(int eventID, IFsmCallback *fsmobj)
{
doFsmEvent(eventID, fsmobj);
while(!queueEvent.empty()){
int eventID = queueEvent.front();
queueEvent.pop();
doFsmEvent(eventID, fsmobj);
}
return 0;
}
int StateFSM::getActionID(int curState, int eventID, int &nextState, int &actionID)
{
map<int, fsmState>::iterator stateIter;
stateIter = mapState.find(curState);
if(stateIter != mapState.end()) {
fsmState state = stateIter->second;
vector<fsmTransition>::iterator traniter;
for ( traniter = state.vecTransition.begin() ; traniter != state.vecTransition.end() ; traniter++ )
{
fsmTransition transition = *traniter;
if(transition.eventID == eventID){
nextState = transition.nextState;
actionID = transition.actionID;
return 0;
}
}
return -2; //curstate has no such event
}else{
return -1; //no such state
}
}