内存的使用是c++中最频繁的,记录一下,方便以后使用。
由于时间原因,未经过太仔细的测试。仅供参考。
头文件:
#include <Windows.h>
#pragma pack(push,1) //开始定义数据包, 采用字节对齐方式
/*----------------------包头---------------------*/
typedef struct tagPACKAGEHEAD
{
BYTE Version;
WORD Command;
WORD nDataLen;//包体的长度
}PACKAGE_HEAD;
#pragma pack(pop) //结束定义数据包, 恢复原来对齐方式
class InterLock
{
public:
void Lock()
{
while (true == InterlockedExchange((LONG*)&m_bLockRec, true))
{
Sleep(0);
}
}
void Unlock()
{
InterlockedExchange((LONG*)&m_bLockRec, false);
}
private:
bool m_bLockRec;
};
class MutexImpl
{
public:
MutexImpl(){::InitializeCriticalSection(&m_oMutex);}
~MutexImpl(){::DeleteCriticalSection(&m_oMutex);}
public:
void Lock()
{
::EnterCriticalSection(&m_oMutex);
}
void Unlock()
{
::LeaveCriticalSection(&m_oMutex);
}
private:
CRITICAL_SECTION m_oMutex;
};
class CDataBufferPool
{
public:
CDataBufferPool() : m_pBuff(0),m_nSize(0),m_nOffset(0),m_PacketHeadLen(0)
{};
~CDataBufferPool()
{}
public:
bool InitBuffer(unsigned int iMaxLen, int ipaglen);
BOOL AddBuff( char *pBuff, int nLen );
int GetFullPacket( char *Buf, int& nLen );
protected:
int GetFreeSize();
private:
char* m_pBuff;
unsigned int m_nSize;
unsigned int m_nOffset;
unsigned int m_PacketHeadLen;
MutexImpl m_cs;
};
bool CDataBufferPool::InitBuffer(unsigned int iMaxLen, int ipaglen)
{
m_nSize = iMaxLen;
m_nOffset = 0;
m_pBuff = (char*)malloc(m_nSize);
m_PacketHeadLen = ipaglen;
if (0 != m_pBuff)
{
return true;
}
return false;
}
int CDataBufferPool::GetFreeSize()
{
return m_nSize-m_nOffset;
}
/*****************************************************************************
Description:添加数据到缓存
Input:pBuff[in]-待添加的数据;nLen[in]-待添加数据长度
Return: 如果当前缓冲区没有足够的空间存放pBuff则返回FALSE;否则返回TRUE。
******************************************************************************/
BOOL CDataBufferPool::AddBuff( char *pBuff, int nLen )
{
m_cs.Lock();///临界区锁
if ( nLen <= 0 )
{
m_cs.Unlock();
return FALSE;
}
if ( nLen <= GetFreeSize() )///判断剩余空间是否足够存放nLen长的数据
{
memcpy(m_pBuff + m_nOffset, pBuff, nLen);
m_nOffset += nLen;
}
else///若不够则扩充原有的空间
{
m_nSize = m_nSize+m_nSize;
char *pnew_buffer = 0;
if (0 != m_pBuff)
{
pnew_buffer = (char*)realloc(m_pBuff,m_nSize);
}
else
{
pnew_buffer = (char*)malloc(m_nSize);
}
if (0 == pnew_buffer)
{
return false;
}
memcpy(m_pBuff + m_nOffset, pBuff, nLen);
m_nOffset += nLen;
return true;
//
//char *p = m_pBuff;
//m_nSize += nLen*2;//每次增长2*nLen
//m_pBuff = new char[m_nSize];
//memcpy(m_pBuff,p,m_nOffset);
//delete []p;
//memcpy(m_pBuff + m_nOffset, pBuff, nLen);
//m_nOffset += nLen;
//m_cs.Unlock();
//return FALSE;
}
m_cs.Unlock();
return TRUE;
}
/*****************************************************************************
Description:获取一个完整的包
Input:Buf[out]-获取到的数据;nLen[out]-获取到的数据长度
Return: 1、当前缓冲区不够一个包头的数据 2、当前缓冲区不够一个包体的数据
******************************************************************************/
int CDataBufferPool::GetFullPacket( char *Buf, int& nLen )
{
m_cs.Lock();
if ( m_nOffset < m_PacketHeadLen )//当前缓冲区不够一个包头的数据
{
m_cs.Unlock();
return 1;
}
PACKAGE_HEAD *p = (PACKAGE_HEAD *)m_pBuff;
if( (m_nOffset-m_PacketHeadLen) < (int)p->nDataLen )//当前缓冲区不够一个包体的数据
{
m_cs.Unlock();
return 2;
}
//判断包的合法性
/* int IsIntegrallity = ValidatePackIntegrality(p);
if( IsIntegrallity != 0 )
{
m_cs.Unlock();
return IsIntegrallity;
}
*/
nLen = m_PacketHeadLen+p->nDataLen;
memcpy( Buf, m_pBuff, nLen );
m_nOffset -= nLen;
memcpy( m_pBuff, m_pBuff+nLen, m_nOffset );
m_cs.Unlock();
return 0;
}
//
class CCircularBufferPool
{
public:
CCircularBufferPool() : m_pBuffer(0), m_iBufSize(0), m_iHeadPos(0), m_iTailPos(0), m_PacketHeadLen(0),m_iOldBufferSize(0)
{};
~CCircularBufferPool(){}
public:
bool InitBuffer(unsigned int iMaxLen, int ipaglen);
BOOL AddBuff(char *pBuff, int nLen);
int GetFullPacket( char *Buf, int& nLen );
protected:
void GetData(char *pData, int len, bool Delete);
bool IsOverFlowCondition(int ilen);
bool BufferResize(int ilen);
bool IsIndexOverFlow(int nLen);
unsigned int GetValidCount();
private:
char *m_pBuffer;
unsigned int m_iBufSize;
unsigned int m_iHeadPos;
unsigned int m_iTailPos;
unsigned int m_PacketHeadLen;
unsigned int m_iOldBufferSize;
MutexImpl m_cs;
};
bool CCircularBufferPool::InitBuffer(unsigned int iMaxLen, int ipaglen)
{
m_iBufSize = iMaxLen;
m_iOldBufferSize = m_iBufSize;
m_iHeadPos = 0;
m_iTailPos = 0;
m_pBuffer = (char*)malloc(m_iBufSize);
m_PacketHeadLen = ipaglen;
if (0 != m_pBuffer)
{
return true;
}
return false;
}
bool CCircularBufferPool::IsOverFlowCondition(int ilen)
{
if (m_iTailPos >= m_iHeadPos)
return (ilen > (m_iBufSize - (m_iTailPos-m_iHeadPos)));
else if (m_iTailPos < m_iHeadPos)
{
return m_iHeadPos - m_iTailPos;
}
}
bool CCircularBufferPool::BufferResize(int ilen)
{
m_cs.Lock();
m_iBufSize = m_iBufSize+m_iBufSize+ilen;
char *pnew_buffer = 0;
if (0 != m_pBuffer)
{
pnew_buffer = (char*)realloc(m_pBuffer,m_iBufSize);
}
else
{
pnew_buffer = (char*)malloc(m_iBufSize);
}
if (0 == pnew_buffer)
{
m_cs.Unlock();
return false;
}
memcpy(m_pBuffer+m_iOldBufferSize, m_pBuffer, m_iTailPos);
m_iTailPos = m_iOldBufferSize+m_iTailPos;
m_iOldBufferSize = m_iBufSize;
m_cs.Unlock();
return true;
}
bool CCircularBufferPool::IsIndexOverFlow(int nLen)
{
return m_iTailPos+nLen > m_iBufSize;
}
unsigned int CCircularBufferPool::GetValidCount()
{
if (m_iTailPos >= m_iHeadPos)
{
return m_iTailPos - m_iHeadPos;
}
else
{
return m_iBufSize -(m_iHeadPos-m_iTailPos);
}
}
BOOL CCircularBufferPool::AddBuff(char *pBuff, int nLen)
{
if( nLen <= 0 )
return 1;
m_cs.Lock();
while (IsOverFlowCondition(nLen))///判断缓冲区剩余空间是否够存放len长的数据
{
BufferResize(nLen);///若不够,则扩充缓冲区.
}
if (IsIndexOverFlow(nLen))///判断"尾"指针的位置.
{
int FirstCopyLen = m_iBufSize-m_iTailPos;
int SecondCopyLen = nLen - FirstCopyLen;
CopyMemory(m_pBuffer+m_iTailPos, pBuff, FirstCopyLen);
if (SecondCopyLen)
{
CopyMemory(m_pBuffer, pBuff+FirstCopyLen, SecondCopyLen);
m_iTailPos = SecondCopyLen;
}
else
m_iTailPos = 0;
}
else
{
CopyMemory(m_pBuffer+m_iTailPos, pBuff, nLen);
m_iTailPos += nLen;
}
m_cs.Unlock();
return 0;
}
void CCircularBufferPool::GetData(char *pData, int len, bool Delete)
{
if (len < m_iBufSize-m_iHeadPos)
{
CopyMemory(pData, m_pBuffer+m_iHeadPos, len);
if(Delete==true)
m_iHeadPos += len;
}
else
{
int fc, sc;
fc = m_iBufSize-m_iHeadPos;
sc = len - fc;
CopyMemory(pData, m_pBuffer+m_iHeadPos, fc);
if (sc) CopyMemory(pData+fc, m_pBuffer, sc);
if(Delete==true)
m_iHeadPos = sc;
if(m_iHeadPos >= m_iBufSize)
m_iHeadPos = 0;
}
}
//
//进行自定义包的解析
//
int CCircularBufferPool::GetFullPacket( char *Buf, int &nLen )
{
m_cs.Lock();
if( GetValidCount() < m_PacketHeadLen )//当前缓冲区不够一个包头的数据
{
m_cs.Unlock();
return 1;
}
GetData(Buf,m_PacketHeadLen,false);
PACKAGE_HEAD *p = (PACKAGE_HEAD *)Buf;
if( (GetValidCount()-m_PacketHeadLen) < (int)p->nDataLen )//当前缓冲区不够一个包体的数据
{
m_cs.Unlock();
return 2;
}
//判断包的合法性
//int IsIntegrallity = ValidatePackIntegrality(p);
//if( IsIntegrallity != 0 )
//{
// m_cs.Unlock();
// return IsIntegrallity;
//}
GetData(Buf,m_PacketHeadLen+p->nDataLen,true);
nLen = m_PacketHeadLen+p->nDataLen;
m_cs.Unlock();
return 0;
}
template<class BUFFER>
class TplBuffer
{
public:
bool InitBuffer(unsigned int iMaxLen, int ipaglen);
BOOL AddBuff( char *pBuff, int nLen );
int GetFullPacket( char *Buf, int& nLen );
private:
BUFFER m_buffer;
};
template<class BUFFER>
bool TplBuffer<BUFFER>::InitBuffer(unsigned int iMaxLen, int ipaglen)
{
return m_buffer.InitBuffer(iMaxLen, ipaglen);
}
template<class BUFFER>
BOOL TplBuffer<BUFFER>::AddBuff( char *pBuff, int nLen )
{
return m_buffer.AddBuff(pBuff, nLen);
}
template<class BUFFER>
int TplBuffer<BUFFER>::GetFullPacket( char *Buf, int& nLen )
{
return m_buffer.GetFullPacket(Buf, nLen);
}
例子:
TplBuffer<CDataBufferPool> tplDataBuff;
TplBuffer<CCircularBufferPool> tplCirBuff;
int isize = sizeof(PACKAGE_HEAD);
tplDataBuff.InitBuffer(1024*1024, sizeof(PACKAGE_HEAD));
tplCirBuff.InitBuffer(1024*1024, sizeof(PACKAGE_HEAD));
PACKAGE_HEAD pheader1, pheader2;
std::string strtest1("012345"), strTest2("0567890");
pheader1.Version = 10;
pheader1.Command = 100;
pheader1.nDataLen = strtest1.length();
pheader2.Version = 20;
pheader2.Command = 200;
pheader2.nDataLen = strTest2.length();
tplDataBuff.AddBuff((char*)(&pheader1), isize);
tplDataBuff.AddBuff((char*)strtest1.c_str(), strtest1.length());
tplCirBuff.AddBuff((char*)(&pheader2), isize);
tplCirBuff.AddBuff((char*)strTest2.c_str(), strTest2.length());
char*pch1 = new char[512], *pch2 = new char[512];
memset(pch1, 0, 512);
memset(pch2, 0, 512);
int ireallen1 = isize + strtest1.length();
int ireallen2 = isize + strTest2.length();
int iret1 = tplDataBuff.GetFullPacket(pch1,ireallen1);
int iret2 = tplCirBuff.GetFullPacket(pch2, ireallen2);
PACKAGE_HEAD *ph1 = (PACKAGE_HEAD*)pch1;
PACKAGE_HEAD *ph2 = (PACKAGE_HEAD*)pch2;
std::string strph1(pch1 + isize);
std::string strph2(pch2 + isize);
也可以在这里看。
http://download.csdn.net/detail/flyingleo1981/6703163