一个简易的线性队列

原来的判断算法有点问题,内存很快就耗尽,修改后如下:
 
#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;
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值