#pragma once // 下列 ifdef 块是创建使从 DLL 导出更简单的 // 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 DIOSSMACHINE_EXPORTS // 符号编译的。在使用此 DLL 的 // 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将 // DIOSSMACHINE_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的 // 符号视为是被导出的。 #ifndef DIOSSMACHINE_EXPORTS #ifdef _WIN64 #ifdef _DEBUG #pragma comment(lib, "DiosSMachineX64D.lib") #else #pragma comment(lib, "DiosSMachineX64.lib") #endif #else #ifdef _DEBUG #pragma comment(lib, "DiosSMachineD.lib") #else #pragma comment(lib, "DiosSMachine.lib") #endif #endif #endif #ifdef DIOSSMACHINE_EXPORTS #define DIOSSMACHINE_API __declspec(dllexport) #define DIOSSMACHINE_C_API extern "C" __declspec(dllexport) #else #define DIOSSMACHINE_API __declspec(dllimport) #define DIOSSMACHINE_C_API extern "C" __declspec(dllimport) #endif #include "ResDataObject.h" #include "DiosThread.h" #include "MsgCircle.h" #include "DiosLock.h" #include "MsgQueue.h" #include using namespace std; #define TIMEOUT_TEMP (3000) #define DiosErrorType "Error" //行为,失败,超时等正常执行时错误 #define DiosFrameError "Frame" //人为的错误发送 #define DiosSeqError "Seq" #define DiosStmEntryPosName "StateMachineEntry" #define DiosStmExitPosName "StateMachineExit" #define DiosTopStateMachineName ("SMOuter") typedef enum _DiosStMachineRet { DIOSSMRET_NG, DIOSSMRET_OK, DIOSSMRET_TIMEOUT, DIOSSMRET_EXIT, DIOSSMRET_MAX }DIOSSTMRET; //assert,通用的事件和錯誤的事件處理上有所不同 //最终有个==的判断,到时候错误和事件的处理方案不一样 #define DiosStmEvtInfo "DiosStmEvtInfo" //JSON格式,EVT事件相关的必须有,而INFO相关的是附加内容,可有可无 /* { "evtkey" : "evt内容", "DiosStmEvtInfo" : "错误内容 or 事件INFO or 其他附加信息" } */ class DIOSSMACHINE_API DiosStMEvt { ResDataObject *m_pEvt; ResDataObject *m_pInfo; public: DiosStMEvt(); DiosStMEvt(const DiosStMEvt &tValue); ~DiosStMEvt(); bool SetEvt(const char* pKey, INT Val, const char *pInfo = NULL); bool SetEvt(const char* pKey, const char *pVal, const char *pInfo = NULL); DiosStMEvt& operator = (const DiosStMEvt &tValue); bool operator == (const DiosStMEvt &Obj); const char *encode(); bool decode(const char *pdata); bool IsEmpty(); ResDataObject& GetEvtContext(); }; //state route pos class DIOSSMACHINE_API DiosStMRouteLine { bool m_ActiveState; bool m_InRoute; DWORD m_Timeout; DiosStMEvt *m_pEvt; string *m_pSrcRoutePos; string *m_pGuard; string *m_pDesRoutePos; public: DiosStMRouteLine(); DiosStMRouteLine(const DiosStMRouteLine &tValue); virtual ~DiosStMRouteLine(); void SetRoute(DiosStMEvt &evt, const char* pGuard, const char* pDes); void SetRoute(DiosStMEvt &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 DiosStMEvt *(); DiosStMRouteLine& operator = (const DiosStMRouteLine &tValue); DWORD GetTimeout(); }; class DIOSSMACHINE_API DiosStMRoutePos { bool m_ActiveState; DWORD m_Timeout; string *m_pRoutePosName; vector *m_pOutRouteLineVec; public: DiosStMRoutePos(); DiosStMRoutePos(const char *pName); virtual ~DiosStMRoutePos(); virtual bool IsSMachine();//no void SetName(const char *pName); const char* GetName(); bool PosAddOutRouteLine(DiosStMEvt &Evt, const char *pSrcPosName, const char *pGuardName, const char *pDesPosName); DWORD GetRouteLineCount(); DiosStMRouteLine **GetOutRouteLineVec(); DiosStMRouteLine *operator [](DiosStMEvt &Evt); void Active(bool state, DWORD timeout); bool GetActiveState(); DWORD GetTimeout(); }; class DIOSSMACHINE_API DiosSMachineIF : public DiosLock { DiosSMachineIF *m_pParent; string *m_pStateMachineName; HANDLE m_StateCangeEvt; HANDLE m_RunningState; DiosStMRouteLine* StateMachineWaitForEvents(int &ExtEvtIndex, DiosStMEvt& Evt);//[< 0]:Local or outline, [>= 0]: externalEvtIndex protected: DiosStMRoutePos *m_pCurrentRoutePos; MsgCircle *m_pArrivedEvts; //routepos map *m_pRoutePosMap; //inline vector *m_pRouteInLineMap; //external size_t m_RouteExternalEvtCount; DiosStMRouteLine** m_pRouteExternalMap; void ClearState(bool bClearEvent = true);//reset DIOSSTMRET TransToPos(const char *pPosName); void PostError(const char *pErrorVal,const char *pErrorInfo = NULL); DiosStMRouteLine *GetEntryRouteLine(); INT ExecStateMachine(HANDLE ThreadExitEvt,DiosStMRouteLine *pExternalWaitEvts[], size_t , bool bClear = true); INT EnterSubStateMachine(HANDLE ThreadExitEvt, DiosStMEvt& Evt); bool PrePareStateMachine(); bool GetRunningState(DWORD waittime = 0); void SetRunningState(bool Running); virtual void PushStateChange(ResDataObject &ChangedPos);//statemachinename:statemachinepos public: DiosSMachineIF(void); virtual ~DiosSMachineIF(void); void SetStateMachineName(const char *pszName); const char *GetStateMachineName(); void SetParentSMachine(DiosSMachineIF *pParent); //for this IF virtual bool IsSMachine();//yes void CopyEvtTo(DiosSMachineIF *pDes); //init state machine //第一个节点的接入比较特殊,所以做了个函数 bool AddEntryRoutePos(DiosStMRoutePos *pPos); bool AddRoutePos(DiosStMRoutePos *pPos); bool AddInRouteLine(DiosStMEvt &Evt, const char *pGuardName, const char *pDesPosName); bool AddOutRouteLine(DiosStMEvt &Evt,const char *pSrcPosName,const char *pGuardName,const char *pDesPosName); //active state machine bool ActiveRoutePos(const char *pPosName, DWORD timeout = TIMEOUT_TEMP); bool ActiveRouteLine(DiosStMEvt &Evt, DWORD timeout = TIMEOUT_TEMP); bool DeActiveAll(); DiosStMRoutePos *GetCurrentRoutePos(); //evt bool PushEvent(DiosStMEvt &Evt); bool PopEvent(DiosStMEvt &Evt); bool PeekEvent(DiosStMEvt &Evt); HANDLE GetEvtNotifyHandle(); HANDLE GetStateChangeEvtHandle(); //for state machine thread virtual DIOSSTMRET StateMachineEntry(DWORD timeout);//Begin状态点 virtual DIOSSTMRET StateMachineExit(DWORD timeout);//End状态点 virtual DIOSSTMRET StateMachineAction(const char *pAction, DWORD timeout); virtual DIOSSTMRET StateMachineGuard(const char *pGuard, DWORD timeout); //返回值的定义 //因为全局事件,本状态机事件,本状态点事件都需要监控 //所以 //返回值为负:退出状态机 //返回值为正: 0 <= EvtIdx < CountOfLocal + CountOfExternal + CountOfOutpath // 至于那个数组的事件,可以自行推算 // 例: Outpath第二个事件 => EvtIdx = CountOfLocal + CountOfExternal + 1 //关于TIMEOUT:函数中wait的是OutpathEvts,LocalEvts和ExternalEvts是没有必要等待,有就有,没有就没有.... virtual int StateMachineWaitForEvents( DiosStMRouteLine *pLocalEvts[], DWORD CountOfLocal, DiosStMRouteLine *pExternalEvts[], DWORD CountOfExternal, DiosStMRouteLine *pOutpathEvts[], DWORD CountOfOutpath, DWORD timeout, DiosStMEvt& Evt ); }; class DIOSSMACHINE_API DiosSMachine : public Dios_Thread,public DiosSMachineIF { protected: virtual bool OnStartThread(); virtual bool Exec(); HANDLE m_StateQuedEvent; ResDataObject m_LastHitStatePos; MsgQueue *m_pStatePosList; virtual void PushStateChange(ResDataObject &ChangedPos);//statemachinename:statemachinepos public: DiosSMachine(void); virtual ~DiosSMachine(void); void SetStateMachineLog(const char *pszLogTitle); bool PopStateChange(ResDataObject &LastPos); HANDLE GetStateQuedEvent(); //for other threads to call bool StartStateMachine(DiosStMRouteLine *pExternalWaitEvts[], DWORD WaitCount); void StopStateMachine(DWORD timeout); }; class DIOSSMACHINE_API DiosSubSMachine : public DiosStMRoutePos, public DiosSMachineIF { protected: public: DiosSubSMachine(void); DiosSubSMachine(const char *pName); virtual ~DiosSubSMachine(void); virtual bool IsSMachine();//yes };