DiosSMachine.h 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. #pragma once
  2. // 下列 ifdef 块是创建使从 DLL 导出更简单的
  3. // 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 DIOSSMACHINE_EXPORTS
  4. // 符号编译的。在使用此 DLL 的
  5. // 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
  6. // DIOSSMACHINE_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
  7. // 符号视为是被导出的。
  8. #ifndef DIOSSMACHINE_EXPORTS
  9. #ifdef _WIN64
  10. #ifdef _DEBUG
  11. #pragma comment(lib, "DiosSMachineX64D.lib")
  12. #else
  13. #pragma comment(lib, "DiosSMachineX64.lib")
  14. #endif
  15. #else
  16. #ifdef _DEBUG
  17. #pragma comment(lib, "DiosSMachineD.lib")
  18. #else
  19. #pragma comment(lib, "DiosSMachine.lib")
  20. #endif
  21. #endif
  22. #endif
  23. #ifdef DIOSSMACHINE_EXPORTS
  24. #define DIOSSMACHINE_API __declspec(dllexport)
  25. #define DIOSSMACHINE_C_API extern "C" __declspec(dllexport)
  26. #else
  27. #define DIOSSMACHINE_API __declspec(dllimport)
  28. #define DIOSSMACHINE_C_API extern "C" __declspec(dllimport)
  29. #endif
  30. #include "ResDataObject.h"
  31. #include "DiosThread.h"
  32. #include "MsgCircle.h"
  33. #include "DiosLock.h"
  34. #include "MsgQueue.h"
  35. #include <map>
  36. using namespace std;
  37. #define TIMEOUT_TEMP (3000)
  38. #define DiosErrorType "Error"
  39. //行为,失败,超时等正常执行时错误
  40. #define DiosFrameError "Frame"
  41. //人为的错误发送
  42. #define DiosSeqError "Seq"
  43. #define DiosStmEntryPosName "StateMachineEntry"
  44. #define DiosStmExitPosName "StateMachineExit"
  45. #define DiosTopStateMachineName ("SMOuter")
  46. typedef enum _DiosStMachineRet
  47. {
  48. DIOSSMRET_NG,
  49. DIOSSMRET_OK,
  50. DIOSSMRET_TIMEOUT,
  51. DIOSSMRET_EXIT,
  52. DIOSSMRET_MAX
  53. }DIOSSTMRET;
  54. //assert,通用的事件和錯誤的事件處理上有所不同
  55. //最终有个==的判断,到时候错误和事件的处理方案不一样
  56. #define DiosStmEvtInfo "DiosStmEvtInfo"
  57. //JSON格式,EVT事件相关的必须有,而INFO相关的是附加内容,可有可无
  58. /*
  59. {
  60. "evtkey" : "evt内容",
  61. "DiosStmEvtInfo" : "错误内容 or 事件INFO or 其他附加信息"
  62. }
  63. */
  64. class DIOSSMACHINE_API DiosStMEvt
  65. {
  66. ResDataObject *m_pEvt;
  67. ResDataObject *m_pInfo;
  68. public:
  69. DiosStMEvt();
  70. DiosStMEvt(const DiosStMEvt &tValue);
  71. ~DiosStMEvt();
  72. bool SetEvt(const char* pKey, INT Val, const char *pInfo = NULL);
  73. bool SetEvt(const char* pKey, const char *pVal, const char *pInfo = NULL);
  74. DiosStMEvt& operator = (const DiosStMEvt &tValue);
  75. bool operator == (const DiosStMEvt &Obj);
  76. const char *encode();
  77. bool decode(const char *pdata);
  78. bool IsEmpty();
  79. ResDataObject& GetEvtContext();
  80. };
  81. //state route pos
  82. class DIOSSMACHINE_API DiosStMRouteLine
  83. {
  84. bool m_ActiveState;
  85. bool m_InRoute;
  86. DWORD m_Timeout;
  87. DiosStMEvt *m_pEvt;
  88. string *m_pSrcRoutePos;
  89. string *m_pGuard;
  90. string *m_pDesRoutePos;
  91. public:
  92. DiosStMRouteLine();
  93. DiosStMRouteLine(const DiosStMRouteLine &tValue);
  94. virtual ~DiosStMRouteLine();
  95. void SetRoute(DiosStMEvt &evt, const char* pGuard, const char* pDes);
  96. void SetRoute(DiosStMEvt &evt, const char* pSrc,const char* pGuard, const char* pDes);
  97. const char* GetDesName();
  98. const char* GetSrcName();
  99. const char* GetGuardName();
  100. bool GetRouteType();//true:in,false:out
  101. void Active(bool state, DWORD timeout);
  102. bool GetActiveState();
  103. operator DiosStMEvt *();
  104. DiosStMRouteLine& operator = (const DiosStMRouteLine &tValue);
  105. DWORD GetTimeout();
  106. };
  107. class DIOSSMACHINE_API DiosStMRoutePos
  108. {
  109. bool m_ActiveState;
  110. DWORD m_Timeout;
  111. string *m_pRoutePosName;
  112. vector<DiosStMRouteLine *> *m_pOutRouteLineVec;
  113. public:
  114. DiosStMRoutePos();
  115. DiosStMRoutePos(const char *pName);
  116. virtual ~DiosStMRoutePos();
  117. virtual bool IsSMachine();//no
  118. void SetName(const char *pName);
  119. const char* GetName();
  120. bool PosAddOutRouteLine(DiosStMEvt &Evt, const char *pSrcPosName, const char *pGuardName, const char *pDesPosName);
  121. DWORD GetRouteLineCount();
  122. DiosStMRouteLine **GetOutRouteLineVec();
  123. DiosStMRouteLine *operator [](DiosStMEvt &Evt);
  124. void Active(bool state, DWORD timeout);
  125. bool GetActiveState();
  126. DWORD GetTimeout();
  127. };
  128. class DIOSSMACHINE_API DiosSMachineIF : public DiosLock
  129. {
  130. DiosSMachineIF *m_pParent;
  131. string *m_pStateMachineName;
  132. HANDLE m_StateCangeEvt;
  133. HANDLE m_RunningState;
  134. DiosStMRouteLine* StateMachineWaitForEvents(int &ExtEvtIndex, DiosStMEvt& Evt);//[< 0]:Local or outline, [>= 0]: externalEvtIndex
  135. protected:
  136. DiosStMRoutePos *m_pCurrentRoutePos;
  137. MsgCircle<DiosStMEvt> *m_pArrivedEvts;
  138. //routepos
  139. map<string, DiosStMRoutePos*> *m_pRoutePosMap;
  140. //inline
  141. vector<DiosStMRouteLine*> *m_pRouteInLineMap;
  142. //external
  143. size_t m_RouteExternalEvtCount;
  144. DiosStMRouteLine** m_pRouteExternalMap;
  145. void ClearState(bool bClearEvent = true);//reset
  146. DIOSSTMRET TransToPos(const char *pPosName);
  147. void PostError(const char *pErrorVal,const char *pErrorInfo = NULL);
  148. DiosStMRouteLine *GetEntryRouteLine();
  149. INT ExecStateMachine(HANDLE ThreadExitEvt,DiosStMRouteLine *pExternalWaitEvts[], size_t , bool bClear = true);
  150. INT EnterSubStateMachine(HANDLE ThreadExitEvt, DiosStMEvt& Evt);
  151. bool PrePareStateMachine();
  152. bool GetRunningState(DWORD waittime = 0);
  153. void SetRunningState(bool Running);
  154. virtual void PushStateChange(ResDataObject &ChangedPos);//statemachinename:statemachinepos
  155. public:
  156. DiosSMachineIF(void);
  157. virtual ~DiosSMachineIF(void);
  158. void SetStateMachineName(const char *pszName);
  159. const char *GetStateMachineName();
  160. void SetParentSMachine(DiosSMachineIF *pParent);
  161. //for this IF
  162. virtual bool IsSMachine();//yes
  163. void CopyEvtTo(DiosSMachineIF *pDes);
  164. //init state machine
  165. //第一个节点的接入比较特殊,所以做了个函数
  166. bool AddEntryRoutePos(DiosStMRoutePos *pPos);
  167. bool AddRoutePos(DiosStMRoutePos *pPos);
  168. bool AddInRouteLine(DiosStMEvt &Evt, const char *pGuardName, const char *pDesPosName);
  169. bool AddOutRouteLine(DiosStMEvt &Evt,const char *pSrcPosName,const char *pGuardName,const char *pDesPosName);
  170. //active state machine
  171. bool ActiveRoutePos(const char *pPosName, DWORD timeout = TIMEOUT_TEMP);
  172. bool ActiveRouteLine(DiosStMEvt &Evt, DWORD timeout = TIMEOUT_TEMP);
  173. bool DeActiveAll();
  174. DiosStMRoutePos *GetCurrentRoutePos();
  175. //evt
  176. bool PushEvent(DiosStMEvt &Evt);
  177. bool PopEvent(DiosStMEvt &Evt);
  178. bool PeekEvent(DiosStMEvt &Evt);
  179. HANDLE GetEvtNotifyHandle();
  180. HANDLE GetStateChangeEvtHandle();
  181. //for state machine thread
  182. virtual DIOSSTMRET StateMachineEntry(DWORD timeout);//Begin状态点
  183. virtual DIOSSTMRET StateMachineExit(DWORD timeout);//End状态点
  184. virtual DIOSSTMRET StateMachineAction(const char *pAction, DWORD timeout);
  185. virtual DIOSSTMRET StateMachineGuard(const char *pGuard, DWORD timeout);
  186. //返回值的定义
  187. //因为全局事件,本状态机事件,本状态点事件都需要监控
  188. //所以
  189. //返回值为负:退出状态机
  190. //返回值为正: 0 <= EvtIdx < CountOfLocal + CountOfExternal + CountOfOutpath
  191. // 至于那个数组的事件,可以自行推算
  192. // 例: Outpath第二个事件 => EvtIdx = CountOfLocal + CountOfExternal + 1
  193. //关于TIMEOUT:函数中wait的是OutpathEvts,LocalEvts和ExternalEvts是没有必要等待,有就有,没有就没有....
  194. virtual int StateMachineWaitForEvents(
  195. DiosStMRouteLine *pLocalEvts[], DWORD CountOfLocal,
  196. DiosStMRouteLine *pExternalEvts[], DWORD CountOfExternal,
  197. DiosStMRouteLine *pOutpathEvts[], DWORD CountOfOutpath,
  198. DWORD timeout, DiosStMEvt& Evt
  199. );
  200. };
  201. class DIOSSMACHINE_API DiosSMachine : public Dios_Thread,public DiosSMachineIF
  202. {
  203. protected:
  204. virtual bool OnStartThread();
  205. virtual bool Exec();
  206. HANDLE m_StateQuedEvent;
  207. ResDataObject m_LastHitStatePos;
  208. MsgQueue<ResDataObject> *m_pStatePosList;
  209. virtual void PushStateChange(ResDataObject &ChangedPos);//statemachinename:statemachinepos
  210. public:
  211. DiosSMachine(void);
  212. virtual ~DiosSMachine(void);
  213. void SetStateMachineLog(const char *pszLogTitle);
  214. bool PopStateChange(ResDataObject &LastPos);
  215. HANDLE GetStateQuedEvent();
  216. //for other threads to call
  217. bool StartStateMachine(DiosStMRouteLine *pExternalWaitEvts[], DWORD WaitCount);
  218. void StopStateMachine(DWORD timeout);
  219. };
  220. class DIOSSMACHINE_API DiosSubSMachine : public DiosStMRoutePos, public DiosSMachineIF
  221. {
  222. protected:
  223. public:
  224. DiosSubSMachine(void);
  225. DiosSubSMachine(const char *pName);
  226. virtual ~DiosSubSMachine(void);
  227. virtual bool IsSMachine();//yes
  228. };