如何实现一个循环缓冲区模型

来源:互联网 发布:java开发工作流 编辑:程序博客网 时间:2024/05/22 02:27

下面是一个RingBuffer模型的完整实现,欢迎读者参考和指正:

 

typedef  unsigned char  BYTE;
 template
 class RingBuffer {
 public:
    typedef size_t   size_type;
    typedef GenericLocker  _BufferLocker;

    RingBuffer() : m_pushPos(0), m_popPos(0), m_count(0) {
        assert(N > 0);
        m_pRingBuffer = new BYTE[N];
    }

    ~RingBuffer() { delete []m_pRingBuffer; }

    RingBuffer(const RingBuffer& copy) : m_popPos(0) {
        assert(N > 0);
        m_pRingBuffer = new BYTE[N];
        size_type rearLen = N - copy.m_popPos;
        if (rearLen >= copy.m_count) {
              ::memmove(m_pRingBuffer,
                                  ©.m_pRingBuffer[copy.m_popPos],
                                  copy.m_count);
        }
        else {
              ::memmove(m_pRingBuffer,
                                  ©.m_pRingBuffer[copy.m_popPos],
                                  rearLen);
              ::memmove(m_pRingBuffer + rearLen,
                                  copy.m_pRingBuffer,

                                  copy.m_count - rearLen);
        }
        m_pushPos = m_count = copy.m_count;
    }

    RingBuffer& operator=(const RingBuffer& other) {
        if (this != &other) {
              _BufferLocker guard(m_mutex);
              RingBuffer temp(other);        // invoke copy constructor
              _Swap(temp);                      // this->_Swap();
        }
        return (*this);
    }

    bool is_full() const {
        _BufferLocker guard(m_mutex);
        return (m_count == N);
    }

    bool is_empty() const {
        _BufferLocker guard(m_mutex);
        return (m_count == 0);
    }

    size_type size() const {
        _BufferLocker guard(m_mutex);
        return m_count;
    }

    size_type capacity() const { return N; }

    size_type push(const BYTE *data, size_type length) {
        assert(data != NULL);
        _BufferLocker guard(m_mutex);
        if (length == 0 || length > (N - m_count))
            return 0;
        size_type rearLen = N - m_pushPos;    // 尾部剩余空间
        if (length <= rearLen) {
            ::memmove(&m_pRingBuffer[m_pushPos], data, length);
            m_pushPos += length;
            m_pushPos %= N;              // 调整新的push位置
        }else{
            ::memmove(&m_pRingBuffer[m_pushPos], data, rearLen);
            ::memmove(m_pRingBuffer, data + rearLen, length - rearLen);
            m_pushPos = length - rearLen;    // 调整新的push位置
            }
        m_count += length;
        return (length);
    }

    size_type pop(BYTE *buf, size_type length) {
        assert(buf != NULL);
        _BufferLocker guard(m_mutex);
        if (length == 0 || length > m_count)
            return 0;
        size_type rearLen = N - m_popPos;    // 尾部剩余数据
        if (length <= rearLen) {
            ::memmove(buf, &m_pRingBuffer[m_popPos], length);
            m_popPos += length;
            m_popPos %= N;             // 调整新的pop位置
        }else {
            ::memmove(buf, &m_pRingBuffer[m_popPos], rearLen);
            ::memmove(buf + rearLen, m_pRingBuffer, length - rearLen);
            m_popPos = length - rearLen;    // 调整新的pop位置
            }
        m_count -= length;
        return (length);
    }

    void clear() {
        _BufferLocker guard(m_mutex);
        m_pushPos = 0, m_popPos = 0, m_count = 0;
    }

private:
    BYTE                *m_pRingBuffer;     // buffer
    size_type           m_pushPos;          // 新的push位置:pushPos=

                                                            // (popPos+count)% N
    size_type           m_popPos;           // 新的pop位置
    size_type           m_count;              // 有效字节数
    CriticalSection  m_mutex;
};




原创粉丝点击