#pragma once // 下列 ifdef 块是创建使从 DLL 导出更简单的 // 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 SHAREMEM_NODE_EXPORTS // 符号编译的。在使用此 DLL 的 // 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将 // SHAREMEM_NODE_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的 // 符号视为是被导出的。 // #ifndef _JUST_USE_API #ifndef SHAREMEM_NODE_EXPORTS #ifdef _WIN64 #ifdef _DEBUG #pragma comment(lib, "ShareMem_NodeX64D.lib") #else #pragma comment(lib, "ShareMem_NodeX64.lib") #endif #else #ifdef _DEBUG #pragma comment(lib, "ShareMem_NodeD.lib") #else #pragma comment(lib, "ShareMem_Node.lib") #endif #endif #endif #ifdef SHAREMEM_NODE_EXPORTS #define SHAREMEM_NODE_API __declspec(dllexport) #define SHAREMEM_NODE_C_API extern "C" __declspec(dllexport) #else #define SHAREMEM_NODE_API __declspec(dllimport) #define SHAREMEM_NODE_C_API extern "C" __declspec(dllimport) #endif #else #define SHAREMEM_NODE_API #define SHAREMEM_NODE_C_API #endif /* 分2个操作方:输入方,输出方 输入输出的原子操作: One way 传输:InLock,DataLock,设置异步,写入,DirtyFlag,DataUnlock,InUnLock,通知IN. 输出方异步操作:OutLock,DataLock,读取,CleanFlag,DataUnlock,OutUnlock. Double Way 传输:InLock,DataLock,设置同步,写入,DirtyFlag,DataUnlock,通知IN,等待通知OUT. 输出方异步操作:OutLock,DataLock,读取&进行操作&写入,DataUnlock,OutUnlock,通知OUT. 输入方等待:通知OUT获取,DataLock,读取,CleanFlag,DataUnLock,InUnLock. 输入输出的管理操作: 1.检索到有空的SMNODE和检索有DirtyFlag的SMNODE. */ #define STK_SM_TIMEOUT (INFINITE) #define STK_SM_NODE_COUNT (8) /* 做了一次计算,最大的数据INPUT量为500K不到. 只是为了读取做成1M,一次可以发起26万次Req,接近1000天的Req. */ #define STK_SM_NODE_SIZE (1024*1024*1) #define STK_NODE_NAME_TMP "stk_nd_n" #define STK_WIF_EVT_NAME "stk_smif_w" #define STK_RIF_EVT_NAME "stk_smif_r" typedef enum _In_or_Out{ STK_SM_WRITE, STK_SM_READ, STK_SM_DATA, STK_SM_MAX }STK_SM_OP; //内存结构 //头信息 typedef struct _stk_Sm_Head { volatile DWORD DrityFlag;//1:dirty,0:clean volatile DWORD Lock[STK_SM_MAX];//Tid or 0 volatile DWORD LockRefCount[STK_SM_MAX]; volatile DWORD SyncMode;//1:sync,0:async volatile DWORD BuffSize;//real buff size volatile DWORD DataSize;//used data size }STK_ST_SM_HEAD; //数据区 //数据头 typedef struct _Stk_Data_Head { UINT64 uTime;//Create时间 DWORD TaskKey;//STK_BLK_DATATYPE char szCode[16]; DWORD Block;//normally is 0 DWORD StartPos;//for import,本块数据在整个数据序列中的偏移位置 DWORD VecCount;//VEC的个数 DWORD VecSize;//VEC的数组大小(后续的以第一个VECSIZE为准,NORMAL,HAND,L2等TASK需要遵从) DWORD ParamCount;//VEC以外的参数个数 INT Param[4]; }STK_DATA_HEAD; //[数据CONTEXT] #pragma warning (push) #pragma warning (disable : 4200) typedef enum _Stk_DataContext_Type { STK_DC_VEC32, STK_DC_VEC64, STK_DC_STR, STK_DC_MAX }STK_DC_TYPE; typedef struct _Stk_Data_Context32 { STK_DC_TYPE Type; DWORD Key; DWORD Size;//size in Count DWORD Rev;//for 64bit FLOAT VecContext[0]; }STK_DATA_CONTEXT32; typedef struct _Stk_Data_Context64 { STK_DC_TYPE Type; DWORD Key; DWORD Size;//size in Count DWORD Rev;//for 64bit UINT64 VecContext[0]; }STK_DATA_CONTEXT64; typedef struct _Stk_Data_Context_Str { STK_DC_TYPE Type; DWORD Key; DWORD Size;//size in byte DWORD Rev;//for 64bit char szStr[0];//make sure it's size qualifies to (val % sizeof(DWORD) == 0) }STK_DATA_CONTEXT_STR; typedef union _Stk_Data_Context { struct { STK_DC_TYPE Type; DWORD Key; DWORD Size;//size in Count DWORD Rev;//for 64bit }Common; STK_DATA_CONTEXT32 Context32; STK_DATA_CONTEXT64 Context64; STK_DATA_CONTEXT_STR ContextStr; }STK_DATA_CONTEXT; #pragma warning (pop) // 此类是从 ShareMem_Node.dll 导出的 class SHAREMEM_NODE_API ShareMem_Node { PVOID m_SmBuff; HANDLE m_hMapping; /* 本Notify只用于双方更新完数据后给对方发起通知. 至于节点释放通知,由主IF对象中的2个R/W事件对象进行管理. */ HANDLE m_Notify[STK_SM_MAX];//write & read STK_ST_SM_HEAD* GetHead(); bool Lock_EnterCriticalSection(STK_SM_OP op, DWORD TryCount); void Lock_LeaveCriticalSection(STK_SM_OP op); public: ShareMem_Node(); virtual ~ShareMem_Node(); bool CreateNode(const char *pNodeName); bool OpenNode(const char *pNodeName); void ClearNode(); HANDLE GetEvtHandle(STK_SM_OP op); DWORD Lock(STK_SM_OP op); void UnLock(STK_SM_OP op); DWORD GetDirtyFlag(); void SetDirtyFlag(DWORD flag); DWORD GetSyncMode(); void SetSyncMode(DWORD Sync); DWORD GetBuffSize(); DWORD GetDataSize(); void SetDataSize(DWORD Size); void UpdateDataSize(); PVOID GetData();//get data buff STK_DATA_HEAD *GetDataHead(); STK_DATA_CONTEXT *GetDataContext(DWORD Idx);//Get Exist one STK_DATA_CONTEXT *GetLastNewDataContext();//get last new one //业务功能 //异步操作-------------------------------------------------------------- //Async Request from Writer(单向写入) //--API:GetNode (帮你筛选&操作: DirtyFlag == 0 && WriteLock) //dataLock //1.update data //2.update datasize //3.update syncmode =0 (async) //4.set DirtyFlag = 1 //dataUnLock //Set ReadEvt,GlobalReadEvt //WriteUnlock //Async Read from Writer(单向读取) //--API:GetNode (帮你筛选&操作: DirtyFlag == 1 && ReadLock) //DataLock //0.check syncmode == 0 (async) //1.process data //---------below is clean job //2.update datasize to 0 //3.set DirtyFlag = 0 //DataUnLock //Set WriteEvt,GlobalWriteEvt //ReadUnLock //同步操作-------------------------------------------------------------- //sync Read from Writer(线程读写) //--API:GetNode (帮你筛选&操作: DirtyFlag == 1 && ReadLock) //DataLock //0.check syncmode == 1(sync) //1.process data //---------below is response job //2.update data with response //3.update datasize //4.set DirtyFlag = 0(目的是为了提示已经写入数据) //DataUnLock //Set WriteEvt //ReadUnLock //线程Write: //Step1:---------------------- //线程write: //--API:GetNode (帮你筛选&操作: DirtyFlag == 0 && WriteLock) //dataLock //1.update data //2.update datasize //3.update syncmode =1 (sync) //4.set DirtyFlag = 1 //dataUnLock //Set ReadEvt,GlobalReadEvt //WaitFor EvtOfWrite //dataLock //先读取Response数据,并保存。 //dataUnLock //goto step2 //Step2:-------------------- //线程write: //dataLock //1.update data //2.update datasize //3.update syncmode =1 (sync) //4.set DirtyFlag = 1 //dataUnLock //Set ReadEvt //WaitFor EvtOfWrite //dataLock //先读取Response数据,并保存。 //dataUnLock //goto step3 //Step3:-------------------- //Step4:-------------------- //Step...:-------------------- //LastStep:(数据为空) //线程write: //dataLock //1.update data //2.update datasize = 0 //3.update syncmode =0 (async) //4.set DirtyFlag = 1 //dataUnLock //Set ReadEvt //WriteUnlock }; SHAREMEM_NODE_C_API DWORD STK_GetMaxDataSize(); SHAREMEM_NODE_C_API HANDLE STK_GetNotifyHandle(STK_SM_OP op); SHAREMEM_NODE_C_API bool STK_CreateSMIF();//server端用 SHAREMEM_NODE_C_API bool STK_OpenSMIF();//Client端用 SHAREMEM_NODE_C_API void STK_CloseSMIF(); //1.check dirtyflag,if dirty or clean //2.try lock readlock or writelock,and check again. //3.if succeed return node. //4.if failed,then relase it. SHAREMEM_NODE_C_API ShareMem_Node *STK_GetNode(STK_SM_OP op, DWORD timeout = INFINITE); SHAREMEM_NODE_C_API void STK_NotifyAvalable(STK_SM_OP op, ShareMem_Node *pNode = NULL); SHAREMEM_NODE_C_API void STK_NotifyRelease(STK_SM_OP op, ShareMem_Node *pNode); SHAREMEM_NODE_C_API void STK_CleanUp(ShareMem_Node *pNode);//Reader的节点释放 //后面的数据先到情况下,重新放入队列 SHAREMEM_NODE_C_API void STK_RestoreNodeForRead(ShareMem_Node *pNode); SHAREMEM_NODE_C_API bool STK_CheckDataIntegrity(ShareMem_Node *pNode); //业务模块模板 //异步接口 //如果数据很大,内部不停的循环保存. //SHAREMEM_NODE_C_API bool STK_WriteData_Async(STK_DATA_HEAD *pHead, STK_DATA_CONTEXT *pInputData, DWORD timeout = STK_SM_TIMEOUT); SHAREMEM_NODE_C_API bool STK_WriteData_Async(ShareMem_Node *pNode); //同步接口 //RET:有效数据的起始位置 SHAREMEM_NODE_C_API INT STK_WriteData_Sync(ShareMem_Node *pNode, FLOAT *pOutputData, DWORD timeout = STK_SM_TIMEOUT); SHAREMEM_NODE_C_API ShareMem_Node *STK_ReadData_Get(STK_DATA_HEAD *&pHead, STK_DATA_CONTEXT *&pData, DWORD timeout = INFINITE); SHAREMEM_NODE_C_API void STK_ReadData_Finished(ShareMem_Node *pNode);