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

news/2024/7/7 6:47:52

下面是一个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;
};





http://www.niftyadmin.cn/n/3654891.html

相关文章

Android学习第五天————Spinner下拉列表组件

Spinner下拉列表组件用来绑定数据&#xff0c;供用户选择 它有两种方式来绑定数据&#xff0c;一种是通过XML文件来绑定&#xff0c;一种是通过适配器来绑定 1、通过XML文件来绑定数据 创建Spinner组件 <Spinner android:id"id/myspinner"android:layout_width…

如何实现一个循环队列

下面是一个循环队列的完整实现&#xff0c;欢迎读者朋友参考和指正&#xff1a;templateclass CyclicQueue {public:typedef T value_type;typedef size_t size_type;typedef T& reference;typedef const T& …

Android学习第五天————ExpandableListView组件通过适配器BaseExpandableListAdapter实现两层列表项

ExpandableListView是对ListView的扩展&#xff0c;实现了当点击列表项时弹出下一层的列表项 同时它必须要通过相对应的适配器来实现数据的绑定 1、首先在布局文件中创建好组件 <ExpandableListViewandroid:id"id/extendview" android:layout_width"wrap_c…

关于char类型的取值范围

《高质量》一书page 104倒数第三行&#xff0c;说“char的取值范围为[-128, 127)”是不对的&#xff0c;正确的范围表示应该为[-128, 127]或者[-128, 128)。这是个笔误&#xff0c;特此更正&#xff01;感谢读者赵为民&#xff01;

Android学习第五天————AdapterViewFlipper组件

AdapterViewFlipper用来实现显示上一个组件&#xff0c;或显示下一个组件&#xff0c;或者自动播放组件 AdapterViewFlipper也是一个需要适配器来填充数据的组件 首先创建一个AdapterViewFlipper组件&#xff0c;同时添加几个按钮来实现显示上一个或下一个或自动播放的功能 …

两本小书的命运 --- 记《Effective STL》和《The Art Of Deception》两本书的出版翻译过程

这两年来&#xff0c;时常听到读者或者朋友们问我“最近还有新书要出版吗”&#xff0c;我的回答是&#xff0c;有两本拖了很久的书快要出版了。我乐观地估计&#xff0c;这两本书在2005年都能出版&#xff0c;然而&#xff0c;不幸的是&#xff0c;这两本书都未能如期出版。从…

Android学习第六天————android中数据存储的五种方式

数据的存取 1、通过键值对的形式来存读数据 SharedPreferences存储共享变量的文件路径位于“/data/data/应用程序包/shared_prefs”目录下 获取SharedPreferences的两种方式: 1 调用Context对象的getSharedPreferences()方法 2 调用Activity对象的getPreferences()方法 两种方式…

Android学习第七天————通过android提供的XmlPullParserFactory解析XML文件

示例代码 XML文件 <?xml version"1.0" encoding"UTF-8"?><users><user><name>小王</name><age>22</age></user><user><name>小李</name><age>23</age></user><…