Кольцевой буфер для POD-типов
От: avo1981  
Дата: 17.09.10 14:48
Оценка:
Здравствуйте. Понадобился кольцевой буфер для многопоточного приложения. Большая часть того что удалось найти в интернете (в т.ч. <boost/circular_buffer.hpp>) ориентировано на объекты, которые по одному копируются в контейнер , а мне необходимо сохранять массивы структур (POD-типов) в стиле С и копирование каждой структуры будет слишком накладно. Попытался написать свой вариант, но как-то не очень (представлен ниже). Может ли кто-нибудь посоветовать готовое решение (готовый класс с подобным алгоритмом), или написать как сделать это оптимальнее. Заранее спасибо



#include <string.h>
#include <stdio.h>

#define RING_BUFFER_SIZE 25

class RingBuffer
{
public:    

    RingBuffer()
    {
        memset(m_Buffer,0,sizeof(m_Buffer));
        memset(m_BufferCopy,0,sizeof(m_BufferCopy));
        m_begin=0;
        m_end=0;
    }
    ~RingBuffer()
    {
    }    
    int WriteData(const const void *pData, int nDataLen)
    {
        char* pchData=(char*)pData;
        int nFreeSpace=RING_BUFFER_SIZE-m_end;
        
        if(m_begin<=m_end)
        {
            if (nFreeSpace>nDataLen)
            {
                memcpy(&m_Buffer[m_end],pchData,nDataLen);
                m_end+=nDataLen;
                m_Buffer[m_end]='f'; //признак окончания данных (для отладки)
            }
            else
            {
                memcpy(&m_Buffer[m_end],pchData,nFreeSpace);
                memcpy(&m_Buffer[0],pchData+nFreeSpace,nDataLen-nFreeSpace);
                m_end=nDataLen-nFreeSpace;
                m_Buffer[m_end]='f'; //признак окончания данных (для отладки)
                m_begin=m_end+1;
            }
        }
        else
        {
            if (nFreeSpace>nDataLen)
            {
                memcpy(&m_Buffer[m_end],pchData,nDataLen);
                m_end+=nDataLen;
                m_Buffer[m_end]='f'; //признак окончания данных (для отладки)
                m_begin=m_end+1;
            }
            else
            {
                memcpy(&m_Buffer[m_end],pchData,nFreeSpace);
                memcpy(&m_Buffer[0],pchData+(nFreeSpace),nDataLen-nFreeSpace);
                m_end=nDataLen-nFreeSpace;
                m_Buffer[m_end]='f'; //признак окончания данных (для отладки)
                m_begin=m_end+1;
            }
        }

        return 0;
    }

    char* GetBufer()
    {
        memset(m_BufferCopy,0,sizeof(m_BufferCopy));
        if (m_end==m_begin)
            return m_BufferCopy;
        if (m_end>m_begin)
            memcpy(m_BufferCopy,m_Buffer,m_end);
        else
        {
            memcpy(m_BufferCopy,m_Buffer+m_begin,RING_BUFFER_SIZE-m_begin);
            memcpy(m_BufferCopy+(RING_BUFFER_SIZE-m_begin),m_Buffer,m_end);
        }
        return m_BufferCopy;
    };

    int DataLenght()
    {
        if (m_end==m_begin)
            return 0;
        if (m_end>m_begin)
            return m_end;
        else
            return RING_BUFFER_SIZE-1;
    };
    void Clear()
    {
        memset(m_Buffer,0,sizeof(m_Buffer));
        memset(m_BufferCopy,0,sizeof(m_BufferCopy));
        m_begin=0;
        m_end=0;
    };
    
protected:
    char m_Buffer[RING_BUFFER_SIZE];
    char m_BufferCopy[RING_BUFFER_SIZE];
    int    m_nCount;
    int m_begin; //begin data index
    int m_end; //end data index
};

int _tmain(int argc, _TCHAR* argv[])
{         
    char message[]="123456789";
    RingBuffer rb;

    //в одном месте программы
    for (int i=0;i<6;i++)
        rb.WriteData(message,sizeof(message)-1);    
    //..
    //где то в программе
    pthread_mutex_lock(&m_FileMutex);    
    write(m_nFileDesc,rb.GetBufer(),rb.DataLenght());
    rb.Clear();
    pthread_mutex_unlock(&m_FileMutex);
        return 0;    
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.