设计了一个环形字节缓冲区类,可用于通信数据收发的缓冲处理。类的读写及查看接口已经加上了多线程同步访问锁。
环形缓冲区需要有一个读指针(位置)和写指针(位置)。其中读指针由读数据接口来移动,写指针由写数据接口来移动。在读出和写入数据时,要分贝考虑 读指针超前与滞后写指针 两种情况。
(一)头文件:CircleByteBuffer.h
#ifndef CIRCLEBYTEBUFFER_H
#define CIRCLEBYTEBUFFER_H
#include <windows.h>
//临界区锁
class CLock_CS
{
public:
CLock_CS(void)
{
::InitializeCriticalSection(&m_cs);
}
virtual~CLock_CS(void)
{
::DeleteCriticalSection(&m_cs);
}
void Lock(void)
{
::EnterCriticalSection(&m_cs);
}
void Unlock(void)
{
::LeaveCriticalSection(&m_cs);
}
private:
CRITICAL_SECTION m_cs;
};
//自动锁
class CAutoLock
{
public:
CAutoLock(CLock_CS & lock)
: m_lock(lock)
{
m_lock.Lock();
}
virtual~CAutoLock()
{
m_lock.Unlock();
}
private:
CLock_CS & m_lock;
};
//环形字节缓冲区
class CCircleByteBuffer
{
public:
CCircleByteBuffer(int nSize);
virtual~CCircleByteBuffer();
int Write(char * pData, int len);
int Read(char * pData, int len);
bool IsFull();
bool IsEmpty();
private:
int DataLength() const;
int FreeLength() const;
private:
CLock_CS m_cs;
int m_nSize;
int m_nRead;
int m_nWrite;
char * m_pBuf;
};
#endif //CIRCLEBYTEBUFFER_H
(二)实现文件:CircleByteBuffer.cpp
#include "stdafx.h"
#include "CircleByteBuffer.h"
CCircleByteBuffer::CCircleByteBuffer(int nSize)
: m_nSize(nSize)
, m_nRead(0)
, m_nWrite(m_nRead)
{
m_pBuf = new char [m_nSize];
}
CCircleByteBuffer::~CCircleByteBuffer()
{
delete [] m_pBuf;
}
int CCircleByteBuffer::Write(char * pData, int len)
{
CAutoLock lock(m_cs);
if (len <= 0)
return 0;
int free_len = FreeLength() - 1;
if (free_len <= 0)
return 0;
int nData = (free_len >= len) ? len : free_len;
if (m_nRead > m_nWrite) {
memcpy(m_pBuf + m_nWrite, pData, nData);
m_nWrite += nData;
}
else {
int tail_len = m_nSize - m_nWrite;
tail_len = (tail_len >= nData) ? nData : tail_len;
memcpy(m_pBuf + m_nWrite, pData, tail_len);
m_nWrite = (m_nWrite + tail_len) % m_nSize;
memcpy(m_pBuf, pData + tail_len, nData - tail_len);
}
return nData;
}
int CCircleByteBuffer::Read(char * pData, int len)
{
CAutoLock lock(m_cs);
if (len <= 0)
return 0;
int data_len = DataLength();
if (data_len <= 0)
return 0;
int nData = (data_len >= len) ? len : data_len;
if (m_nWrite > m_nRead) {
memcpy(pData, m_pBuf + m_nRead, nData);
m_nRead += nData;
}
else {
int tail_len = m_nSize - m_nRead;
tail_len = (tail_len >= nData) ? nData : tail_len;
memcpy(pData, m_pBuf + m_nRead, tail_len);
m_nRead = (m_nRead + tail_len) % m_nSize;
memcpy(pData + tail_len, m_pBuf, nData - tail_len);
}
return nData;
}
bool CCircleByteBuffer::IsFull()
{
CAutoLock lock(m_cs);
return (FreeLength() == 1);
}
bool CCircleByteBuffer::IsEmpty()
{
CAutoLock lock(m_cs);
return (m_nWrite == m_nRead);
}
int CCircleByteBuffer::DataLength() const
{
int len = m_nWrite - m_nRead;
if (len < 0)
len = m_nSize + len;
return len;
}
int CCircleByteBuffer::FreeLength() const
{
int len = m_nRead - m_nWrite;
if (len <= 0)
len = m_nSize + len;
return len;
}