环形缓冲区类(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
", bytes);
        }
        else
        {
            printf("write wait time out
");
        }
    }
    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
", bytes, realBytes);
//         }
//         else
//         {
//             printf("read wait time out
");
//         }

        //Sleep(1);
        bytes = rand() % 1024;
        realBytes = test.readBuf(pBuf, bytes);
        printf("read byte %d,real byte %d
", 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