ShareMem_Node.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. #pragma once
  2. // 下列 ifdef 块是创建使从 DLL 导出更简单的
  3. // 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 SHAREMEM_NODE_EXPORTS
  4. // 符号编译的。在使用此 DLL 的
  5. // 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
  6. // SHAREMEM_NODE_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
  7. // 符号视为是被导出的。
  8. //
  9. #ifndef _JUST_USE_API
  10. #ifndef SHAREMEM_NODE_EXPORTS
  11. #ifdef _WIN64
  12. #ifdef _DEBUG
  13. #pragma comment(lib, "ShareMem_NodeX64D.lib")
  14. #else
  15. #pragma comment(lib, "ShareMem_NodeX64.lib")
  16. #endif
  17. #else
  18. #ifdef _DEBUG
  19. #pragma comment(lib, "ShareMem_NodeD.lib")
  20. #else
  21. #pragma comment(lib, "ShareMem_Node.lib")
  22. #endif
  23. #endif
  24. #endif
  25. #ifdef SHAREMEM_NODE_EXPORTS
  26. #define SHAREMEM_NODE_API __declspec(dllexport)
  27. #define SHAREMEM_NODE_C_API extern "C" __declspec(dllexport)
  28. #else
  29. #define SHAREMEM_NODE_API __declspec(dllimport)
  30. #define SHAREMEM_NODE_C_API extern "C" __declspec(dllimport)
  31. #endif
  32. #else
  33. #define SHAREMEM_NODE_API
  34. #define SHAREMEM_NODE_C_API
  35. #endif
  36. /*
  37. 分2个操作方:输入方,输出方
  38. 输入输出的原子操作:
  39. One way 传输:InLock,DataLock,设置异步,写入,DirtyFlag,DataUnlock,InUnLock,通知IN.
  40. 输出方异步操作:OutLock,DataLock,读取,CleanFlag,DataUnlock,OutUnlock.
  41. Double Way 传输:InLock,DataLock,设置同步,写入,DirtyFlag,DataUnlock,通知IN,等待通知OUT.
  42. 输出方异步操作:OutLock,DataLock,读取&进行操作&写入,DataUnlock,OutUnlock,通知OUT.
  43. 输入方等待:通知OUT获取,DataLock,读取,CleanFlag,DataUnLock,InUnLock.
  44. 输入输出的管理操作:
  45. 1.检索到有空的SMNODE和检索有DirtyFlag的SMNODE.
  46. */
  47. #define STK_SM_TIMEOUT (INFINITE)
  48. #define STK_SM_NODE_COUNT (8)
  49. /*
  50. 做了一次计算,最大的数据INPUT量为500K不到.
  51. 只是为了读取做成1M,一次可以发起26万次Req,接近1000天的Req.
  52. */
  53. #define STK_SM_NODE_SIZE (1024*1024*1)
  54. #define STK_NODE_NAME_TMP "stk_nd_n"
  55. #define STK_WIF_EVT_NAME "stk_smif_w"
  56. #define STK_RIF_EVT_NAME "stk_smif_r"
  57. typedef enum _In_or_Out{
  58. STK_SM_WRITE,
  59. STK_SM_READ,
  60. STK_SM_DATA,
  61. STK_SM_MAX
  62. }STK_SM_OP;
  63. //内存结构
  64. //头信息
  65. typedef struct _stk_Sm_Head {
  66. volatile DWORD DrityFlag;//1:dirty,0:clean
  67. volatile DWORD Lock[STK_SM_MAX];//Tid or 0
  68. volatile DWORD LockRefCount[STK_SM_MAX];
  69. volatile DWORD SyncMode;//1:sync,0:async
  70. volatile DWORD BuffSize;//real buff size
  71. volatile DWORD DataSize;//used data size
  72. }STK_ST_SM_HEAD;
  73. //数据区
  74. //数据头
  75. typedef struct _Stk_Data_Head {
  76. UINT64 uTime;//Create时间
  77. DWORD TaskKey;//STK_BLK_DATATYPE
  78. char szCode[16];
  79. DWORD Block;//normally is 0
  80. DWORD StartPos;//for import,本块数据在整个数据序列中的偏移位置
  81. DWORD VecCount;//VEC的个数
  82. DWORD VecSize;//VEC的数组大小(后续的以第一个VECSIZE为准,NORMAL,HAND,L2等TASK需要遵从)
  83. DWORD ParamCount;//VEC以外的参数个数
  84. INT Param[4];
  85. }STK_DATA_HEAD;
  86. //[数据CONTEXT]
  87. #pragma warning (push)
  88. #pragma warning (disable : 4200)
  89. typedef enum _Stk_DataContext_Type {
  90. STK_DC_VEC32,
  91. STK_DC_VEC64,
  92. STK_DC_STR,
  93. STK_DC_MAX
  94. }STK_DC_TYPE;
  95. typedef struct _Stk_Data_Context32 {
  96. STK_DC_TYPE Type;
  97. DWORD Key;
  98. DWORD Size;//size in Count
  99. DWORD Rev;//for 64bit
  100. FLOAT VecContext[0];
  101. }STK_DATA_CONTEXT32;
  102. typedef struct _Stk_Data_Context64 {
  103. STK_DC_TYPE Type;
  104. DWORD Key;
  105. DWORD Size;//size in Count
  106. DWORD Rev;//for 64bit
  107. UINT64 VecContext[0];
  108. }STK_DATA_CONTEXT64;
  109. typedef struct _Stk_Data_Context_Str {
  110. STK_DC_TYPE Type;
  111. DWORD Key;
  112. DWORD Size;//size in byte
  113. DWORD Rev;//for 64bit
  114. char szStr[0];//make sure it's size qualifies to (val % sizeof(DWORD) == 0)
  115. }STK_DATA_CONTEXT_STR;
  116. typedef union _Stk_Data_Context
  117. {
  118. struct
  119. {
  120. STK_DC_TYPE Type;
  121. DWORD Key;
  122. DWORD Size;//size in Count
  123. DWORD Rev;//for 64bit
  124. }Common;
  125. STK_DATA_CONTEXT32 Context32;
  126. STK_DATA_CONTEXT64 Context64;
  127. STK_DATA_CONTEXT_STR ContextStr;
  128. }STK_DATA_CONTEXT;
  129. #pragma warning (pop)
  130. // 此类是从 ShareMem_Node.dll 导出的
  131. class SHAREMEM_NODE_API ShareMem_Node {
  132. PVOID m_SmBuff;
  133. HANDLE m_hMapping;
  134. /*
  135. 本Notify只用于双方更新完数据后给对方发起通知.
  136. 至于节点释放通知,由主IF对象中的2个R/W事件对象进行管理.
  137. */
  138. HANDLE m_Notify[STK_SM_MAX];//write & read
  139. STK_ST_SM_HEAD* GetHead();
  140. bool Lock_EnterCriticalSection(STK_SM_OP op, DWORD TryCount);
  141. void Lock_LeaveCriticalSection(STK_SM_OP op);
  142. public:
  143. ShareMem_Node();
  144. virtual ~ShareMem_Node();
  145. bool CreateNode(const char *pNodeName);
  146. bool OpenNode(const char *pNodeName);
  147. void ClearNode();
  148. HANDLE GetEvtHandle(STK_SM_OP op);
  149. DWORD Lock(STK_SM_OP op);
  150. void UnLock(STK_SM_OP op);
  151. DWORD GetDirtyFlag();
  152. void SetDirtyFlag(DWORD flag);
  153. DWORD GetSyncMode();
  154. void SetSyncMode(DWORD Sync);
  155. DWORD GetBuffSize();
  156. DWORD GetDataSize();
  157. void SetDataSize(DWORD Size);
  158. void UpdateDataSize();
  159. PVOID GetData();//get data buff
  160. STK_DATA_HEAD *GetDataHead();
  161. STK_DATA_CONTEXT *GetDataContext(DWORD Idx);//Get Exist one
  162. STK_DATA_CONTEXT *GetLastNewDataContext();//get last new one
  163. //业务功能
  164. //异步操作--------------------------------------------------------------
  165. //Async Request from Writer(单向写入)
  166. //--API:GetNode (帮你筛选&操作: DirtyFlag == 0 && WriteLock)
  167. //dataLock
  168. //1.update data
  169. //2.update datasize
  170. //3.update syncmode =0 (async)
  171. //4.set DirtyFlag = 1
  172. //dataUnLock
  173. //Set ReadEvt,GlobalReadEvt
  174. //WriteUnlock
  175. //Async Read from Writer(单向读取)
  176. //--API:GetNode (帮你筛选&操作: DirtyFlag == 1 && ReadLock)
  177. //DataLock
  178. //0.check syncmode == 0 (async)
  179. //1.process data
  180. //---------below is clean job
  181. //2.update datasize to 0
  182. //3.set DirtyFlag = 0
  183. //DataUnLock
  184. //Set WriteEvt,GlobalWriteEvt
  185. //ReadUnLock
  186. //同步操作--------------------------------------------------------------
  187. //sync Read from Writer(线程读写)
  188. //--API:GetNode (帮你筛选&操作: DirtyFlag == 1 && ReadLock)
  189. //DataLock
  190. //0.check syncmode == 1(sync)
  191. //1.process data
  192. //---------below is response job
  193. //2.update data with response
  194. //3.update datasize
  195. //4.set DirtyFlag = 0(目的是为了提示已经写入数据)
  196. //DataUnLock
  197. //Set WriteEvt
  198. //ReadUnLock
  199. //线程Write:
  200. //Step1:----------------------
  201. //线程write:
  202. //--API:GetNode (帮你筛选&操作: DirtyFlag == 0 && WriteLock)
  203. //dataLock
  204. //1.update data
  205. //2.update datasize
  206. //3.update syncmode =1 (sync)
  207. //4.set DirtyFlag = 1
  208. //dataUnLock
  209. //Set ReadEvt,GlobalReadEvt
  210. //WaitFor EvtOfWrite
  211. //dataLock
  212. //先读取Response数据,并保存。
  213. //dataUnLock
  214. //goto step2
  215. //Step2:--------------------
  216. //线程write:
  217. //dataLock
  218. //1.update data
  219. //2.update datasize
  220. //3.update syncmode =1 (sync)
  221. //4.set DirtyFlag = 1
  222. //dataUnLock
  223. //Set ReadEvt
  224. //WaitFor EvtOfWrite
  225. //dataLock
  226. //先读取Response数据,并保存。
  227. //dataUnLock
  228. //goto step3
  229. //Step3:--------------------
  230. //Step4:--------------------
  231. //Step...:--------------------
  232. //LastStep:(数据为空)
  233. //线程write:
  234. //dataLock
  235. //1.update data
  236. //2.update datasize = 0
  237. //3.update syncmode =0 (async)
  238. //4.set DirtyFlag = 1
  239. //dataUnLock
  240. //Set ReadEvt
  241. //WriteUnlock
  242. };
  243. SHAREMEM_NODE_C_API DWORD STK_GetMaxDataSize();
  244. SHAREMEM_NODE_C_API HANDLE STK_GetNotifyHandle(STK_SM_OP op);
  245. SHAREMEM_NODE_C_API bool STK_CreateSMIF();//server端用
  246. SHAREMEM_NODE_C_API bool STK_OpenSMIF();//Client端用
  247. SHAREMEM_NODE_C_API void STK_CloseSMIF();
  248. //1.check dirtyflag,if dirty or clean
  249. //2.try lock readlock or writelock,and check again.
  250. //3.if succeed return node.
  251. //4.if failed,then relase it.
  252. SHAREMEM_NODE_C_API ShareMem_Node *STK_GetNode(STK_SM_OP op, DWORD timeout = INFINITE);
  253. SHAREMEM_NODE_C_API void STK_NotifyAvalable(STK_SM_OP op, ShareMem_Node *pNode = NULL);
  254. SHAREMEM_NODE_C_API void STK_NotifyRelease(STK_SM_OP op, ShareMem_Node *pNode);
  255. SHAREMEM_NODE_C_API void STK_CleanUp(ShareMem_Node *pNode);//Reader的节点释放
  256. //后面的数据先到情况下,重新放入队列
  257. SHAREMEM_NODE_C_API void STK_RestoreNodeForRead(ShareMem_Node *pNode);
  258. SHAREMEM_NODE_C_API bool STK_CheckDataIntegrity(ShareMem_Node *pNode);
  259. //业务模块模板
  260. //异步接口
  261. //如果数据很大,内部不停的循环保存.
  262. //SHAREMEM_NODE_C_API bool STK_WriteData_Async(STK_DATA_HEAD *pHead, STK_DATA_CONTEXT *pInputData, DWORD timeout = STK_SM_TIMEOUT);
  263. SHAREMEM_NODE_C_API bool STK_WriteData_Async(ShareMem_Node *pNode);
  264. //同步接口
  265. //RET:有效数据的起始位置
  266. SHAREMEM_NODE_C_API INT STK_WriteData_Sync(ShareMem_Node *pNode, FLOAT *pOutputData, DWORD timeout = STK_SM_TIMEOUT);
  267. SHAREMEM_NODE_C_API ShareMem_Node *STK_ReadData_Get(STK_DATA_HEAD *&pHead, STK_DATA_CONTEXT *&pData, DWORD timeout = INFINITE);
  268. SHAREMEM_NODE_C_API void STK_ReadData_Finished(ShareMem_Node *pNode);