サイクルbufferの実装
3391 ワード
ヘッダファイル:
実装:
#define SAFE_ARRAY_DELETE(POINTER) if (POINTER) { delete [] POINTER; POINTER = NULL; }
class CCircleBuffer
{
public:
// construction / destruction
CCircleBuffer();
virtual ~CCircleBuffer();
// create the buffer
void CreateBuffer(int nBytes, int nMaxDirectWriteBytes);
// query
int MaxAdd();
int MaxGet();
// direct writing
__forceinline unsigned char * CCircleBuffer::GetDirectWritePointer()
{
// return a pointer to the tail -- note that it will always be safe to write
// at least m_nMaxDirectWriteBytes since we use an end cap region
return &m_pBuffer[m_nTail];
}
__forceinline void CCircleBuffer::UpdateAfterDirectWrite(int nBytes)
{
// update the tail
m_nTail += nBytes;
// if the tail enters the "end cap" area, set the end cap and loop around
if (m_nTail >= (m_nTotal - m_nMaxDirectWriteBytes))
{
m_nEndCap = m_nTail;
m_nTail = 0;
}
}
// get data
int Get(unsigned char * pBuffer, int nBytes);
// remove / empty
void Empty();
int RemoveHead(int nBytes);
int RemoveTail(int nBytes);
private:
int m_nTotal;
int m_nMaxDirectWriteBytes;
int m_nEndCap;
int m_nHead;
int m_nTail;
unsigned char * m_pBuffer;
};
実装:
#include "CircleBuffer.h"
CCircleBuffer::CCircleBuffer()
{
m_pBuffer = NULL;
m_nTotal = 0;
m_nHead = 0;
m_nTail = 0;
m_nEndCap = 0;
m_nMaxDirectWriteBytes = 0;
}
CCircleBuffer::~CCircleBuffer()
{
SAFE_ARRAY_DELETE(m_pBuffer)
}
void CCircleBuffer::CreateBuffer(int nBytes, int nMaxDirectWriteBytes)
{
SAFE_ARRAY_DELETE(m_pBuffer)
m_nMaxDirectWriteBytes = nMaxDirectWriteBytes;
m_nTotal = nBytes + 1 + nMaxDirectWriteBytes;
m_pBuffer = new unsigned char [m_nTotal];
m_nHead = 0;
m_nTail = 0;
m_nEndCap = m_nTotal;
}
int CCircleBuffer::MaxAdd()
{
int nMaxAdd = (m_nTail >= m_nHead) ? (m_nTotal - 1 - m_nMaxDirectWriteBytes) - (m_nTail - m_nHead) : m_nHead - m_nTail - 1;
return nMaxAdd;
}
int CCircleBuffer::MaxGet()
{
return (m_nTail >= m_nHead) ? m_nTail - m_nHead : (m_nEndCap - m_nHead) + m_nTail;
}
int CCircleBuffer::Get(unsigned char * pBuffer, int nBytes)
{
int nTotalGetBytes = 0;
if (pBuffer != NULL && nBytes > 0)
{
int nHeadBytes = min(m_nEndCap - m_nHead, nBytes);
int nFrontBytes = nBytes - nHeadBytes;
memcpy(&pBuffer[0], &m_pBuffer[m_nHead], nHeadBytes);
nTotalGetBytes = nHeadBytes;
if (nFrontBytes > 0)
{
memcpy(&pBuffer[nHeadBytes], &m_pBuffer[0], nFrontBytes);
nTotalGetBytes += nFrontBytes;
}
RemoveHead(nBytes);
}
return nTotalGetBytes;
}
void CCircleBuffer::Empty()
{
m_nHead = 0;
m_nTail = 0;
m_nEndCap = m_nTotal;
}
int CCircleBuffer::RemoveHead(int nBytes)
{
nBytes = min(MaxGet(), nBytes);
m_nHead += nBytes;
if (m_nHead >= m_nEndCap)
m_nHead -= m_nEndCap;
return nBytes;
}
int CCircleBuffer::RemoveTail(int nBytes)
{
nBytes = min(MaxGet(), nBytes);
m_nTail -= nBytes;
if (m_nTail < 0)
m_nTail += m_nEndCap;
return nBytes;
}