#pragma once #define CCOSSMACHINE_API #define CCOSSMACHINE_C_API extern "C" #include "ResDataObject.h" #include "CcosThread.h" #include "MsgCircle.h" #include "CcosLock.h" #include "MsgQueue.h" #include using namespace std; #define TIMEOUT_TEMP (3000) #define CcosErrorType "Error" //行为,失败,超时等正常执行时错误 #define CcosFrameError "Frame" //人为的错误发送 #define CcosSeqError "Seq" #define CcosStmEntryPosName "StateMachineEntry" #define CcosStmExitPosName "StateMachineExit" #define CcosTopStateMachineName ("SMOuter") typedef enum _CcosStMachineRet { CCOSSMRET_NG, CCOSSMRET_OK, CCOSSMRET_TIMEOUT, CCOSSMRET_EXIT, CCOSSMRET_MAX }CCOSSTMRET; //assert,通用的事件和錯誤的事件處理上有所不同 //最终有个==的判断,到时候错误和事件的处理方案不一样 #define CcosStmEvtInfo "CcosStmEvtInfo" //JSON格式,EVT事件相关的必须有,而INFO相关的是附加内容,可有可无 /* { "evtkey" : "evt内容", "CcosStmEvtInfo" : "错误内容 or 事件INFO or 其他附加信息" } */ class CCOSSMACHINE_API CcosStMEvt { ResDataObject *m_pEvt; ResDataObject *m_pInfo; public: CcosStMEvt(); CcosStMEvt(const CcosStMEvt &tValue); ~CcosStMEvt(); bool SetEvt(const char* pKey, int Val, const char *pInfo = NULL); bool SetEvt(const char* pKey, const char *pVal, const char *pInfo = NULL); CcosStMEvt& operator = (const CcosStMEvt &tValue); bool operator == (const CcosStMEvt &Obj); const char *encode(); bool decode(const char *pdata); bool IsEmpty(); ResDataObject& GetEvtContext(); }; //state route pos class CCOSSMACHINE_API CcosStMRouteLine { bool m_ActiveState; bool m_InRoute; DWORD m_Timeout; CcosStMEvt *m_pEvt; string *m_pSrcRoutePos; string *m_pGuard; string *m_pDesRoutePos; public: CcosStMRouteLine(); CcosStMRouteLine(const CcosStMRouteLine &tValue); virtual ~CcosStMRouteLine(); void SetRoute(CcosStMEvt &evt, const char* pGuard, const char* pDes); void SetRoute(CcosStMEvt &evt, const char* pSrc,const char* pGuard, const char* pDes); const char* GetDesName(); const char* GetSrcName(); const char* GetGuardName(); bool GetRouteType();//true:in,false:out void Active(bool state, DWORD timeout); bool GetActiveState(); operator CcosStMEvt *(); CcosStMRouteLine& operator = (const CcosStMRouteLine &tValue); DWORD GetTimeout(); }; class CCOSSMACHINE_API CcosStMRoutePos { bool m_ActiveState; DWORD m_Timeout; string *m_pRoutePosName; vector *m_pOutRouteLineVec; public: CcosStMRoutePos(); CcosStMRoutePos(const char *pName); virtual ~CcosStMRoutePos(); virtual bool IsSMachine();//no void SetName(const char *pName); const char* GetName(); bool PosAddOutRouteLine(CcosStMEvt &Evt, const char *pSrcPosName, const char *pGuardName, const char *pDesPosName); DWORD GetRouteLineCount(); CcosStMRouteLine **GetOutRouteLineVec(); CcosStMRouteLine *operator [](CcosStMEvt &Evt); void Active(bool state, DWORD timeout); bool GetActiveState(); DWORD GetTimeout(); }; class CCOSSMACHINE_API CcosSMachineIF : public CcosLock { CcosSMachineIF *m_pParent; string *m_pStateMachineName; std::shared_ptr m_StateCangeEvt; std::shared_ptr m_RunningState; CcosStMRouteLine* StateMachineWaitForEvents(int &ExtEvtIndex, CcosStMEvt& Evt);//[< 0]:Local or outline, [>= 0]: externalEvtIndex protected: CcosStMRoutePos *m_pCurrentRoutePos; MsgCircle *m_pArrivedEvts; //routepos map *m_pRoutePosMap; //inline vector *m_pRouteInLineMap; //external size_t m_RouteExternalEvtCount; CcosStMRouteLine** m_pRouteExternalMap; void ClearState(bool bClearEvent = true);//reset CCOSSTMRET TransToPos(const char *pPosName); void PostError(const char *pErrorVal,const char *pErrorInfo = NULL); CcosStMRouteLine *GetEntryRouteLine(); int ExecStateMachine(std::shared_ptr ThreadExitEvt,CcosStMRouteLine *pExternalWaitEvts[], size_t , bool bClear = true); int EnterSubStateMachine(std::shared_ptr ThreadExitEvt, CcosStMEvt& Evt); bool PrePareStateMachine(); bool GetRunningState(DWORD waittime = 0); void SetRunningState(bool Running); virtual void PushStateChange(ResDataObject &ChangedPos);//statemachinename:statemachinepos public: CcosSMachineIF(void); virtual ~CcosSMachineIF(void); void SetStateMachineName(const char *pszName); const char *GetStateMachineName(); void SetParentSMachine(CcosSMachineIF *pParent); //for this IF virtual bool IsSMachine();//yes void CopyEvtTo(CcosSMachineIF *pDes); //init state machine //第一个节点的接入比较特殊,所以做了个函数 bool AddEntryRoutePos(CcosStMRoutePos *pPos); bool AddRoutePos(CcosStMRoutePos *pPos); bool AddInRouteLine(CcosStMEvt &Evt, const char *pGuardName, const char *pDesPosName); bool AddOutRouteLine(CcosStMEvt &Evt,const char *pSrcPosName,const char *pGuardName,const char *pDesPosName); //active state machine bool ActiveRoutePos(const char *pPosName, DWORD timeout = TIMEOUT_TEMP); bool ActiveRouteLine(CcosStMEvt &Evt, DWORD timeout = TIMEOUT_TEMP); bool DeActiveAll(); CcosStMRoutePos *GetCurrentRoutePos(); //evt bool PushEvent(CcosStMEvt &Evt); bool PopEvent(CcosStMEvt &Evt); bool PeekEvent(CcosStMEvt &Evt); std::shared_ptr GetEvtNotifyHandle(); std::shared_ptr GetStateChangeEvtHandle(); //for state machine thread virtual CCOSSTMRET StateMachineEntry(DWORD timeout);//Begin状态点 virtual CCOSSTMRET StateMachineExit(DWORD timeout);//End状态点 virtual CCOSSTMRET StateMachineAction(const char *pAction, DWORD timeout); virtual CCOSSTMRET StateMachineGuard(const char *pGuard, DWORD timeout); //返回值的定义 //因为全局事件,本状态机事件,本状态点事件都需要监控 //所以 //返回值为负:退出状态机 //返回值为正: 0 <= EvtIdx < CountOfLocal + CountOfExternal + CountOfOutpath // 至于那个数组的事件,可以自行推算 // 例: Outpath第二个事件 => EvtIdx = CountOfLocal + CountOfExternal + 1 //关于TIMEOUT:函数中wait的是OutpathEvts,LocalEvts和ExternalEvts是没有必要等待,有就有,没有就没有.... virtual int StateMachineWaitForEvents( CcosStMRouteLine *pLocalEvts[], DWORD CountOfLocal, CcosStMRouteLine *pExternalEvts[], DWORD CountOfExternal, CcosStMRouteLine *pOutpathEvts[], DWORD CountOfOutpath, DWORD timeout, CcosStMEvt& Evt ); }; class CCOSSMACHINE_API CcosSMachine : public Ccos_Thread,public CcosSMachineIF { protected: virtual bool OnStartThread(); virtual bool Exec(); std::shared_ptr m_StateQuedEvent; ResDataObject m_LastHitStatePos; MsgQueue *m_pStatePosList; virtual void PushStateChange(ResDataObject &ChangedPos);//statemachinename:statemachinepos public: CcosSMachine(void); virtual ~CcosSMachine(void); void SetStateMachineLog(const char *pszLogTitle); bool PopStateChange(ResDataObject &LastPos); std::shared_ptr GetStateQuedEvent(); //for other threads to call bool StartStateMachine(CcosStMRouteLine *pExternalWaitEvts[], DWORD WaitCount); void StopStateMachine(DWORD timeout); }; class CCOSSMACHINE_API CcosSubSMachine : public CcosStMRoutePos, public CcosSMachineIF { protected: public: CcosSubSMachine(void); CcosSubSMachine(const char *pName); virtual ~CcosSubSMachine(void); virtual bool IsSMachine();//yes };