环形缓冲区类(C++)附测试程序(转)
CircularBuf.h
#ifndef CIRCULAR_BUF_H
#define CIRCULAR_BUF_H
#include <Windows.h>
#define MULTI_BUF_SIZE 10
#define MULTI_MIN_BUF_DATA_SIZE 5
class CCircularBuf
{
public:
CCircularBuf(void);
~CCircularBuf(void);
//创建缓冲区
long createBuf(const long size, const HANDLE writeEvent, const HANDLE readEvent);
//释放缓冲区
long releaseBuf(void);
//读
long readBuf(char *pBuf, const long bytes);
//写
long writeBuf(const char *pBuf, const long bytes);
private:
//获取写指针
long getWritePos(const long size, long *pos1, long *pos2,
long *len1, long *len2);
//获取读指针
long getReadPos(const long size, long *pos1, long *pos2,
long *len1, long *len2);
//修改写指针
long setWritePos(const long pos);
//修改读指针
long setReadPos(const long pos);
private:
char *pCirBuf;
long lBufSize;
long lMaxRWBufSize;
long lWritePos;
long lReadPos;
HANDLE hWriteEvent;
HANDLE hReadEvent;
CRITICAL_SECTION csCirBuf;
};
#endif
CircularBuf.cpp
#include "stdafx.h"
#include "CircularBuf.h"
CCircularBuf::CCircularBuf(void)
{
pCirBuf = NULL;
lBufSize = 0;
lMaxRWBufSize = 0;
hWriteEvent = 0;
hReadEvent = 0;
lWritePos = 0;
lReadPos = 0;
}
CCircularBuf::~CCircularBuf(void)
{
}
//创建缓冲区
long CCircularBuf::createBuf(long size, const HANDLE writeEvent, const HANDLE readEvent)
{
if (!size || !writeEvent || !readEvent)
{
return -1;
}
pCirBuf = new char [size * MULTI_BUF_SIZE];
if (!pCirBuf)
{
return -1;
}
memset(pCirBuf, 0, size * MULTI_BUF_SIZE);
lMaxRWBufSize = size;
lBufSize = size * MULTI_BUF_SIZE;
hWriteEvent = writeEvent;
hReadEvent = readEvent;
lWritePos = 0;
lReadPos = 0;
InitializeCriticalSection(&csCirBuf);
return 0;
}
//释放缓冲区
long CCircularBuf::releaseBuf(void)
{
if (!lBufSize)
{
return -1;
}
EnterCriticalSection(&csCirBuf);
if (pCirBuf)
{
delete []pCirBuf;
pCirBuf = NULL;
}
lMaxRWBufSize = 0;
lBufSize = 0;
hWriteEvent = 0;
hReadEvent = 0;
lWritePos = 0;
lReadPos = 0;
LeaveCriticalSection(&csCirBuf);
DeleteCriticalSection(&csCirBuf);
return 0;
}
//读
long CCircularBuf::readBuf(char *pBuf, const long bytes)
{
long pos1 = 0;
long pos2 = 0;
long len1 = 0;
long len2 = 0;
long realBytes = 0;
if (bytes > lMaxRWBufSize || !pBuf)
{
return -1;
}
EnterCriticalSection(&csCirBuf);
if (getReadPos(bytes, &pos1, &pos2, &len1, &len2))
{
LeaveCriticalSection(&csCirBuf);
return -1;
}
if (pos2)
{
memcpy(pBuf, &pCirBuf[pos1], len1);
realBytes = len1;
setReadPos(pos1 + len1);
}
else
{
memcpy(pBuf, &pCirBuf[pos1], len1);
memcpy(&pBuf[len1], &pCirBuf, len2);
realBytes = len1 + len2;
setReadPos(len2);
}
LeaveCriticalSection(&csCirBuf);
return realBytes;
}
//写
long CCircularBuf::writeBuf(const char *pBuf, const long bytes)
{
long pos1 = 0;
long pos2 = 0;
long len1 = 0;
long len2 = 0;
long writeBytes = 0;
if (bytes > lMaxRWBufSize || !pBuf)
{
return -1;
}
EnterCriticalSection(&csCirBuf);
if (getWritePos(bytes, &pos1, &pos2, &len1, &len2))
{
LeaveCriticalSection(&csCirBuf);
return -1;
}
if (pos2)
{
memcpy(&pCirBuf[pos1], pBuf, len1);
writeBytes = len1;
setWritePos(pos1 + len1);
}
else
{
memcpy(&pCirBuf[pos1], pBuf, len1);
memcpy(&pCirBuf, &pBuf[len1], len2);
writeBytes = len1 + len2;
setWritePos(len2);
}
LeaveCriticalSection(&csCirBuf);
return writeBytes;
}
//获取写指针
long CCircularBuf::getWritePos(const long size, long *pos1, long *pos2,
long *len1, long *len2)
{
if (!pos1 || !pos2 || *len1 || *len2)
{
return -1;
}
*pos1 = lWritePos;
if (lWritePos < lReadPos)//写指针在读指针左,不可能循环
{
*pos2 = lBufSize;
*len2 = 0;
if (lWritePos + size > lReadPos)
{
*len1 = lReadPos - lWritePos;
}
else
{
*len1 = size;
}
}
else//写指针在读指针右,可能循环
{
if (lWritePos + size > lBufSize)
{
*len1 = lBufSize - lWritePos;
*pos2 = 0;
*len2 = size + lWritePos - lBufSize;
if (*len2 > lReadPos)
{
*len2 = lReadPos;
}
}
else
{
*len1 = size;
*pos2 = lBufSize;
*len2 = 0;
}
}
return 0;
}
//获取读指针
long CCircularBuf::getReadPos(const long size, long *pos1, long *pos2,
long *len1, long *len2)
{
if (!pos1 || !pos2 || *len1 || *len2)
{
return -1;
}
*pos1 = lReadPos;
if (lReadPos <= lWritePos)//读指针在写指针左,不可能循环
{
*pos2 = lBufSize;
*len2 = 0;
if (lReadPos + size > lWritePos)
{
*len1 = lWritePos - lReadPos;
}
else
{
*len1 = size;
}
}
else//读指针在写指针右,可能循环
{
if (lReadPos + size > lBufSize)
{
*len1 = lBufSize - lReadPos;
*pos2 = 0;
*len2 = size + lReadPos - lBufSize;
if (*len2 > lWritePos)
{
*len2 = lWritePos;
}
}
else
{
*len1 = size;
*pos2 = lBufSize;
*len2 = 0;
}
}
return 0;
}
//修改写指针
long CCircularBuf::setWritePos(const long pos)
{
if (pos >= lBufSize)
{
lWritePos = pos - lBufSize;
}
else
{
lWritePos = pos;
}
if (lReadPos > lWritePos)
{
if (lBufSize - lReadPos + lWritePos > MULTI_MIN_BUF_DATA_SIZE * lMaxRWBufSize)
{
SetEvent(hReadEvent);
}
}
else
{
if (lWritePos - lReadPos > MULTI_MIN_BUF_DATA_SIZE * lMaxRWBufSize)
{
SetEvent(hReadEvent);
}
}
return 0;
}
//修改读指针
long CCircularBuf::setReadPos(const long pos)
{
if (pos >= lBufSize)
{
lReadPos = pos - lBufSize;
}
else
{
lReadPos = pos;
}
if (lReadPos > lWritePos)
{
if (lBufSize - lReadPos + lWritePos < MULTI_MIN_BUF_DATA_SIZE * lMaxRWBufSize)
{
SetEvent(hWriteEvent);
}
}
else
{
if (lWritePos - lReadPos < MULTI_MIN_BUF_DATA_SIZE * lMaxRWBufSize)
{
SetEvent(hWriteEvent);
}
}
return 0;
}
test.cpp
// Test.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "CircularBuf.h"
CCircularBuf test;
DWORD WINAPI writeThread(PVOID pvoid)
{
HANDLE hwite = (HANDLE)pvoid;
char pBuf[1024];
long bytes = 0;
while(1)
{
if (WaitForSingleObject(hwite, 5000) == WAIT_OBJECT_0)
{
for (long i = 0; i < 1024; i++)
{
pBuf[i] = i % 0x7F;
}
bytes = test.writeBuf(pBuf, 1024);
printf("write byte %d\n", bytes);
}
else
{
printf("write wait time out\n");
}
}
return 0;
}
DWORD WINAPI readThread(PVOID pvoid)
{
HANDLE hread = (HANDLE)pvoid;
char pBuf[1024];
long realBytes = 0;
long bytes = 0;
long countByte = 0;
realBytes = test.readBuf(pBuf, 0);
while(1)
{
// if (WaitForSingleObject(hread, 5000) == WAIT_OBJECT_0)
// {
// bytes = rand() % 1024;
// realBytes = test.readBuf(pBuf, bytes);
// printf("read byte %d,real byte %d\n", bytes, realBytes);
// }
// else
// {
// printf("read wait time out\n");
// }
//Sleep(1);
bytes = rand() % 1024;
realBytes = test.readBuf(pBuf, bytes);
printf("read byte %d,real byte %d\n", bytes, realBytes);
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
static long size = 1024;
HANDLE hwite, hread;
hwite = CreateEvent(NULL, FALSE, FALSE, NULL);
hread = CreateEvent(NULL, FALSE, FALSE, NULL);
test.createBuf(size, hwite, hread);
CreateThread(NULL, 0, writeThread, (LPVOID)hwite, 0, NULL);
CreateThread(NULL, 0, readThread, (LPVOID)hread, 0, NULL);
while(1)
{
Sleep(1000);
}
test.releaseBuf();
return 0;
}
原帖地址:http://www.cnblogs.com/ark-zhang/archive/2013/04/27/3046427.html
浙公网安备 33010602011771号