原来的判断算法有点问题,内存很快就耗尽,修改后如下:
#include "stdafx.h" #include <assert.h> #include "DataQueue.h" #ifdef _DEBUG #include <iostream> CRITICAL_SECTION g_cs; int g_forDebug = 0; #endif #ifndef __max #define __max(a,b) (((a) > (b)) ? (a) : (b)) #endif CDataQueue::CDataQueue() : m_first(0) , m_last(0) , m_terminalPos(0) , m_dataSize(0) , m_dataPacketCount(0) , m_bufferSize(0) , m_pDataQueueBuffer(nullptr) #ifdef _DEBUG , m_forDebug(g_forDebug++) #endif { #ifdef _DEBUG static bool bFirst = true; if (bFirst) { ::InitializeCriticalSection(&g_cs); } #endif // _DEBUG } CDataQueue::~CDataQueue() { ClearData(true); #ifdef _DEBUG static bool bFirst = true; if (bFirst) { ::DeleteCriticalSection(&g_cs); } #endif } bool CDataQueue::NeedReallocMemory(DWORD dwCopySize) { // m_last <= m_terminalPos; // 所以,如果m_last == m_terminalPos则还没回绕,否则已经绕回到前面。 assert(m_last <= m_terminalPos); if ((m_dataSize + dwCopySize) > m_bufferSize) return true; else if ((m_last == m_terminalPos) && ((m_last + dwCopySize) > m_bufferSize)) { if (m_first >= dwCopySize) m_last = 0; else return true; } else if ((m_last < m_terminalPos) && ((m_last + dwCopySize) > m_first)) return true; return false; } bool CDataQueue::ReallocMemory( WORD wDataSize ) { //申请内存 DWORD dwNewBufferSize = m_bufferSize + __max(m_bufferSize, (wDataSize + sizeof(DWORD)) * 10L); #ifdef _DEBUG EnterCriticalSection(&g_cs); static int i = 0; std::cout << "DataQueue: " << (int)m_forDebug << "#" << i++ <<" ,新缓冲大小 = " << dwNewBufferSize << ", 原缓冲大小 = " << m_bufferSize << ", 包数 " << m_dataPacketCount << ", 数据大小 " << m_dataSize << std::endl; LeaveCriticalSection(&g_cs); #endif BYTE* pNewQueueServiceBuffer = new BYTE[dwNewBufferSize]; if (pNewQueueServiceBuffer == nullptr) { assert(false); return false; } //拷贝数据 if (m_pDataQueueBuffer != nullptr) { DWORD dwPartOneSize = m_terminalPos - m_first; if (dwPartOneSize > 0L) { CopyMemory(pNewQueueServiceBuffer, m_pDataQueueBuffer + m_first, dwPartOneSize); } if (m_dataSize > dwPartOneSize) //说明前面还有数据 { assert((m_last + dwPartOneSize) == m_dataSize); CopyMemory(pNewQueueServiceBuffer + dwPartOneSize, m_pDataQueueBuffer, m_last); } } //调整变量 m_first = 0L; m_last = m_dataSize; m_terminalPos = m_dataSize; m_bufferSize = dwNewBufferSize; delete []m_pDataQueueBuffer; m_pDataQueueBuffer = pNewQueueServiceBuffer; return true; } //负荷信息 void CDataQueue::GetBurthenInfo(DWORD* pDataSize, DWORD* pBufferSize, DWORD* pDataPacketCount) { if (pDataSize) { *pDataSize = m_dataSize; } if (pBufferSize) { *pBufferSize = m_bufferSize; } if (pDataPacketCount) { *pDataPacketCount = m_dataPacketCount; } } //插入数据 bool CDataQueue::InsertData(WORD wIdentifier, void* const pBuffer, WORD wDataSize) { //初始化数据 //DataHeader DataHead; //DataHead.wDataSize = wDataSize; //DataHead.wIdentifier = wIdentifier; DWORD dwDataHeader = MAKELONG(wIdentifier, wDataSize); // wDataSize高位,wIdentifier低位 DWORD dwCopySize = sizeof(DWORD) + wDataSize; if(NeedReallocMemory(dwCopySize)) { if(!ReallocMemory(wDataSize)) { return false; } } //拷贝数据 CopyMemory(m_pDataQueueBuffer + m_last, &dwDataHeader, sizeof(DWORD)); if (wDataSize > 0) { assert(pBuffer != nullptr); CopyMemory(m_pDataQueueBuffer + m_last + sizeof(DWORD), pBuffer, wDataSize); } //调整数据 ++m_dataPacketCount; m_dataSize += dwCopySize; m_last += dwCopySize; m_terminalPos = __max(m_terminalPos, m_last); return true; } //获取数据 bool CDataQueue::GetData(WORD& wDataSize, WORD& wIdentifier, void* pBuffer, WORD wBufferSize) { if (!m_dataPacketCount) { wDataSize = 0; return false; } if (m_first == m_terminalPos) // 已经读取到结尾,回绕到开头。 { m_first = 0L; m_terminalPos = m_last; } //获取指针 assert(m_bufferSize >= (m_first + sizeof(DWORD))); DWORD dwDataHead = *((DWORD*)(m_pDataQueueBuffer + m_first)); wDataSize = HIWORD(dwDataHead); wIdentifier = LOWORD(dwDataHead); if (!pBuffer) { return false; // 用户可能需要知道接收缓冲的大小 } //获取大小 WORD wPacketSize = sizeof(DWORD) + wDataSize; assert(m_bufferSize >= (m_first + wPacketSize)); //判断缓冲 WORD wCopySize = 0; if (wBufferSize >= wDataSize) { wCopySize = wDataSize; } else { return false; // 缓冲区小,用户可以申请大的缓冲再试。 } //拷贝数据 if (wDataSize > 0) { CopyMemory(pBuffer, m_pDataQueueBuffer + (m_first + sizeof(DWORD)), wDataSize); } //效验参数 assert(wPacketSize <= m_dataSize); assert(m_bufferSize >= (m_first + wPacketSize)); //设置变量 --m_dataPacketCount; m_dataSize -= wPacketSize; m_first += wPacketSize; return true; } //删除数据 void CDataQueue::ClearData(bool bFreeMemroy) { //设置变量 m_dataSize = 0L; m_last = 0L; m_terminalPos = 0L; m_first = 0L; m_dataPacketCount = 0L; if (bFreeMemroy) { m_bufferSize = 0; delete []m_pDataQueueBuffer; } }
一个简易的线性队列
最新推荐文章于 2022-10-16 13:19:04 发布