如何利用記憶體池和共享記憶體構建高速的程序間通訊模型
阿新 • • 發佈:2019-02-01
#include "messagequeue.h" #include BYTE* CMssageQueue::mpCurrAddr = nullptr; CMssageQueue::CMssageQueue() { miBegin = 0; miEnd = 0; miOffset = sizeof(this); } CMssageQueue::~CMssageQueue() { } void *CMssageQueue::operator new(size_t size) { return (void*)mpCurrAddr; } CMssageQueue* CMssageQueue::CreateInstance() { return new CMssageQueue(); } void CMssageQueue::SendMessage(char *message,int length) { int nTempMaxLength = 0; int nTempRt = -1; BYTE *pbyCodeBuf; BYTE *pTempSrc = NULL; BYTE *pTempDst = NULL; unsigned int i; if( !message || length <= 0 ) { return; } pbyCodeBuf = MessageBeginAddr(); // 首先判斷是否佇列已滿 if(IsMemFull()) //if( m_stQueueHead.m_nFullFlag ) { return; } nTempMaxLength = GetFreeSize(); nTempRt = miEnd; //空間不足 if((length + sizeof(unsigned short) )> nTempMaxLength) { return; } unsigned short usInLength = (unsigned short) length; pTempDst = &pbyCodeBuf[0]; pTempSrc = (BYTE*) (&usInLength); //寫入的時候我們在資料頭插上資料的長度,方便準確取資料 for( i = 0; i < sizeof(usInLength); i++ ) { pTempDst[miEnd] = pTempSrc[i]; // 拷貝 Code 的長度 miEnd = (miEnd + 1) % GetDataMemSize(); // % 用於防止 Code 結尾的 idx 超出 codequeue } //空閒區在中間 if( miBegin > miEnd ) { memcpy((void *)&pbyCodeBuf[miEnd], (const void *)message, (size_t)usInLength ); } else //空閒區在兩頭 { //尾部放不下需要分段拷貝的情況 if( length > (GetDataMemSize() - miEnd) ) { memcpy((void *)&pbyCodeBuf[miEnd], (const void *)&message[0], (size_t)(GetDataMemSize()- miEnd) ); memcpy((void *)&pbyCodeBuf[0],(const void *)&message[(GetDataMemSize() - miEnd)], (size_t)(length - (GetDataMemSize() - miEnd))); } else { memcpy((void *)&pbyCodeBuf[miEnd], (const void *)&message[0], (size_t)length); } } miEnd = (miEnd + length) % GetDataMemSize(); } int CMssageQueue::GetMessage(BYTE *pOutCode, int *pOutLength) { int nTempMaxLength = 0; int nTempRet = -1; BYTE *pTempSrc; BYTE *pTempDst; unsigned int i; BYTE *pbyCodeBuf; if( !pOutCode || !pOutLength ) { return -1; } nTempMaxLength = GetDataSize(); if (nTempMaxLength <= 0) { return -1; } pbyCodeBuf = MessageBeginAddr(); nTempRet = miBegin; // 如果資料的最大長度不到2(存入資料時在資料頭插入了資料的長度) if( nTempMaxLength < (int)sizeof(short) ) { miBegin = miEnd; return -1; } unsigned short usOutLength; pTempDst = (BYTE *)&usOutLength; // 資料拷貝的目的地址 pTempSrc = (BYTE *)&pbyCodeBuf[0]; // 資料拷貝的源地址 //取出資料的長度 for( i = 0; i < sizeof(short); i++ ) { pTempDst[i] = pTempSrc[miBegin]; miBegin = (miBegin+1) % GetDataMemSize(); } // 將資料長度回傳 *pOutLength = usOutLength; //資料的長度非法 if(usOutLength > (int)(nTempMaxLength - sizeof(short)) || usOutLength < 0 ) { miBegin = miEnd; return -1; } pTempDst = (BYTE *)&pOutCode[0]; // 設定接收 Code 的地址 // 資料在中間 if( miBegin < miEnd ) { memcpy((void *)pTempDst, (const void *)&pTempSrc[miBegin], (size_t)(usOutLength)); } else { if(GetDataMemSize() - miBegin < usOutLength) { memcpy((void *)pTempDst, (const void *)&pTempSrc[miBegin], (size_t)(GetDataMemSize() - miBegin)); pTempDst += (GetDataMemSize() - miBegin); memcpy((void *)pTempDst, (const void *)&pTempSrc[0], (size_t)(usOutLength - (GetDataMemSize() - miBegin))); } else // 否則,直接拷貝 { memcpy((void *)pTempDst, (const void *)&pTempSrc[miBegin], (size_t)(usOutLength)); } } miBegin = (miBegin + usOutLength) % GetDataMemSize(); return usOutLength; } BYTE* CMssageQueue::MessageBeginAddr() { return (BYTE*)(this + miOffset); } bool CMssageQueue::IsMemFull() { return GetFreeSize() <= 0; } //獲取空閒區大小 int CMssageQueue::GetFreeSize() { int freesize = 0; //第一次寫資料前 if( miBegin == miEnd ) { freesize = GetDataMemSize(); } //資料在兩頭 else if( miBegin > miEnd ) { freesize = miBegin - miEnd; } else //資料在中間 { freesize = freesize - (miEnd - miBegin); } //長度應該減去預留部分長度8,保證首尾不會相接 freesize -= EXTRA_BYTE; return freesize; } //獲取資料長度 int CMssageQueue::GetDataSize() { int freesize = GetDataMemSize(); //第一次寫資料前 if( miBegin == miEnd ) { return 0; } //資料在兩頭 else if( miBegin > miEnd ) { return freesize - (miBegin - miEnd); } else //資料在中間 { return miEnd - miBegin; } } int CMssageQueue::GetDataMemSize() { return (int)(MEM_SIZE - sizeof(this)); }