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

原创 2007年09月12日 19:00:00

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

 

typedef  unsigned char  BYTE;
 template<unsigned int N  /*容量(字节数)*/>
 class RingBuffer {
 public:
    typedef size_t   size_type;
    typedef GenericLocker<CriticalSection>  _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<N>& 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,
                                  &copy.m_pRingBuffer[copy.m_popPos],
                                  copy.m_count);
        }
        else {
              ::memmove(m_pRingBuffer,
                                  &copy.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<N>& other) {
        if (this != &other) {
              _BufferLocker guard(m_mutex);
              RingBuffer<N> 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;
};

DDD原著 -- 第三章 绑定模型和实现

领域驱动设计要求模型不仅能够指导早期的分析工作,还应该成为设计的基础。 严格按照基础模型来编写代码,能够使代码更好地表达设计含义,并且是模型更符合设计。 缺乏设计基础概念的软件充其量也只是一种机械化的...
  • lingxyd_0
  • lingxyd_0
  • 2016年06月17日 09:11
  • 426

生产者/消费者模型

产者/消费者模型描述如下:有一个或多个生产者生产某种类型的数据,并防止在缓冲区(可以是数组也可以是队列等数据结构)中;有一个消费者可以从缓冲区中取数据,每次取一项;系统保证避免对缓冲区的重复操作,也就...
  • sicofield
  • sicofield
  • 2013年04月25日 14:19
  • 8968

TensorFlow学习笔记(二):TensorFlow实现线性回归模型

一、线性回归模型中所涉及到API#导入TensorFlow包 import tensorflow as tf #TensorFlow程序分为两个阶段:准备阶段和执行阶段 #--------------...
  • kenwengqie2235
  • kenwengqie2235
  • 2017年11月09日 20:33
  • 115

【Qt OpenGL教程】25:变形和从文件中加载3D物体

这次教程中,我们将学会如何从文件中加载3D模型,并且平滑的从一个模型变形为另一个模型。在这一课里,我们将介绍如何实现模型的变形过程,这将会是效果很棒的一课!...
  • cly116
  • cly116
  • 2015年08月12日 20:29
  • 2064

仅用原生JavaScript手写DOM事件模型

前言 前段时间博客园里有篇很火的帖子2016十家公司前端面试小记,主要讲作者的前端面试经历,其中提到了面试官会考察手写一个简单的DOM事件模型。 “如果上述都ok的话,那么极有可能要求让你【实现事件...
  • GAMEloft9
  • GAMEloft9
  • 2016年04月29日 11:35
  • 6941

数学之美笔录(1):统计语言模型

统计语言模型 (Statistical Language Models)介绍: 在语言处理领域,比如翻译、识别语音、文字识别和进行海量文献的自动检索,出现了两种最基本的方法。第一种方法比较直接,就是...
  • kzq_qmi
  • kzq_qmi
  • 2015年07月01日 19:28
  • 695

如何实现一个文件系统

如何实现一个文件系统 摘要 本章目的是分析在Linux系统中如何实现新的文件系统。在介绍文件系统具体实现前先介绍文件系统的概念和作用,抽象出了文件系统概念模型。熟悉文件系统的内涵后,我...
  • wh8_2011
  • wh8_2011
  • 2015年11月24日 09:17
  • 1340

Java实现生产者消费者模型

生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品。解决生产者/消费者问题的方法可分为两类:(1)采用某种机制...
  • ILOVESMJ
  • ILOVESMJ
  • 2016年09月19日 17:07
  • 6302

css盒子模型+小三角

1. 引言   从这一节开始,我们就进入本系列的第三部分——css呈现。本部分将描述css在页面的几种布局和呈现的特性。包括两类:文字、块。   第一类——文字。这部分相对比较简单一些,例...
  • w1019945543
  • w1019945543
  • 2016年04月05日 23:14
  • 569

一个异步并发模型的实现

在工作中我们经常会碰到并发处理的情况,如我们需要并发上传5张图片到文件服务器等待全部上传完毕后拿到返回链接再提交给逻辑服务器,这个时候5张图片的并发上传模型可以采用Callable+Future+Co...
  • junjianzhang
  • junjianzhang
  • 2015年04月11日 13:57
  • 335
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:如何实现一个循环缓冲区模型
举报原因:
原因补充:

(最多只允许输入30个字)