zoukankan      html  css  js  c++  java
  • 环形缓冲区,魔戒lordrings,boost的circular_buffer

    写服务器的代码时,为了减少内存的分配,我们很多时候需要一个池子,讲需要分配的资源先new出来,放在池子里面。这个池子的总长度(容量)应该是大部分时候是固定,

    表面看来,这种要求用std::list实现最简单,list可以在开始和结尾的地方增加删除。但你会发现,如果使用std::list作为池子,性能会是你很头疼的一个东西,std::list分配一个加入一个对象,或者释放一个对象,可能都会对应一次new,delete操作。如果这样的操作频繁,std::list就会成为效率的瓶颈。我的一个通讯程序,接受和发送的buffer都考虑用一个池子,而每一个链接的发送数据,也会考虑放在一个池子里面。开始我就是用的list,后来用Oprofile,测试发现了这个问题。我就考虑要换容器实现。于是就有了这个lordrings。后来发现服务器所有需要池子的地方,都可以用这个魔戒解决问题。

    看了一下Boost的设计实现circular_buffer提供的接口,以及代码。circular_buffer和我的设计思路几乎一致。使用一个内存数据区作为数据存放区,可以在开始位置和结束位置进行插入和删除操作,开始和,结束位置的指针可以变化,通过模除保证队列可以循环;长度可以扩展;如果队列已经满了,提供插入的时候提供是否覆盖的选择。

     

                                                                                                                                   图1 BOOST的circular_buffer的设计实现图

    不同的地方大约有2点,第一点是circular_buffer的实现完全符合stl的规范,包括分配器,和迭代器等,而我的实现省去了这些东西,我在内部实现了头部尾部的增加,删除,也实现了任意位置的[]方法。第二点是我的lordrings使用了一个小技巧记录区分数据区是空还是满,就是增加一个数据的空间,当记录开始位置的指针等于结束位置的指针的时候表示空,当开始位置和结束位置相差1的时候表示满。而BOOST的circular_buffer增加了一个记录尺寸的变量。现在默默感觉了一下,BOOST的这个方法比较我的要好一点,估计我当时写的时候被自己的内存PIPE设计影响了。

    最后把代码贴出来,写的时候在听张楚的姐姐,当时对模板的感觉已经开始入门了。大致进入了侯捷所说的第3个阶段吧。哈哈。

    /******************************************************************************************

    Copyright           : 2000-2004,FXL.

    FileName            :

    Author              : Sail(ZENGXING)//Author name here

    Version             :

    Date Of Creation    : 2006年3月11日

    Description         : 一个循环的DEQUE,可以控制在数据满的情况下,是否覆盖

     

    Others              : 原来取名cyc_deque,但是一天和Linker聊天他说说他写的类似的类名字是rings,我觉得这个

                            名字比较酷,所以选择这个名字,越来越觉得这个类好用。

    Function List       :

    1.  ......

    Modification History:

    1.Date  :

    Author  :

    Modification  :

    喔姐姐,我想回家,牵着我的手,我有些困了

     

    ******************************************************************************************/

     

     

    #ifndef _ZEN_EXTEND_STD_CYC_DEQUE_H_

    #define _ZEN_EXTEND_STD_CYC_DEQUE_H_

     

     

    namespace zenlib

    {

     

     

    template<class _value_type >

    class lordrings

    {

    protected:

        //循环队列的起始位置

        size_t                cycdeque_start_;

        //循环队列的结束位置,注意我使用的是前开后闭

        size_t                cycdeque_end_;

        //队列的长度,使队列的容量+1

        size_t                cycdeque_len_;

        //存放数据的指针

        _value_type           *value_ptr_;

     

    public:

        //构造函数,后面必须调用,initialize

        lordrings():

            cycdeque_start_(0),

            cycdeque_end_(cycdeque_start_),

            cycdeque_len_(1),

            value_ptr_(NULL)

        {

        }

       

        //构造函数,后面完全没有必要调用,initialize

        //因为要形成一个前闭后开的空间,所以cycdeque_len_比实际要求的数据长度+1

        lordrings(size_t data_len):

            cycdeque_start_(0),

            cycdeque_end_(cycdeque_start_),

            cycdeque_len_(data_len+1),

            value_ptr_(NULL)

        {

            assert(data_len > 0);

            value_ptr_ = new _value_type[cycdeque_len_];

        }

     

        ~lordrings()

        {

            if(value_ptr_)

            {

                delete[] value_ptr_;

                value_ptr_ = NULL;

            }

        }

       

        //因为要形成一个前闭后开的空间,所以cycdeque_len_比实际要求的数据长度+1

        void initialize(size_t data_len)

        {

            assert(data_len > 0);

     

            cycdeque_start_ =0;

            cycdeque_end_ = cycdeque_start_;

            cycdeque_len_ = data_len+1;

            //清理现场

            if(value_ptr_)

            {

                delete[] value_ptr_;

                value_ptr_ = NULL;

            }

            value_ptr_ = new _value_type[cycdeque_len_];

        }

     

        //

        void finit()

        {

            cycdeque_start_ = 0;

            cycdeque_end_ = cycdeque_start_;

            cycdeque_len_ = 1;

            //清理现场

            if(value_ptr_)

            {

                delete[] value_ptr_;

                value_ptr_ = NULL;

            }

        }

     

        //重新

        void clear()

        {

            cycdeque_start_ =0;

            cycdeque_end_ = cycdeque_start_;

        }

           

        //尺寸空间

        inline size_t size() const

        {

            //

            if ( cycdeque_end_ >= cycdeque_start_ )

            {

                return cycdeque_end_ - cycdeque_start_ ;

            }

            else

            {

                return cycdeque_end_+cycdeque_len_ -cycdeque_start_ ;

            }

        }

        //返回空闲空间的大小

        inline size_t freesize() const

        {

            return cycdeque_len_ -size() -1;

        }

        //返回队列的容量

        inline size_t capacity() const

        {

            return cycdeque_len_ -1;

        }

        //检查是否已经满了

        inline bool full() const

        {

            //如果结束+1%

            if((cycdeque_end_ + 1)%cycdeque_len_ ==cycdeque_start_)

            {

                return true;

            }

            return false;

        }

     

        //判断队列是否为空

        inline bool empty() const

        {

            //如果发现开始==结束

            if(cycdeque_start_ == cycdeque_end_)

            {

                return true;

            }

            return false;

        }

     

        //重新分配一个空间,

        bool resize(size_t new_size)

        {

            assert(new_size > 0);

     

            size_t deque_size = size();

            //如果原来的尺寸大于新的尺寸,无法扩展

            if( deque_size > new_size )

            {

                return false;

            }

            _value_type *new_value_ptr = new _value_type[new_size+1];

     

            //调整几个内部参数

            cycdeque_start_ =0;

            cycdeque_end_ = deque_size;

            cycdeque_len_ = new_size+1;

           

            //如果原来有数据

            if(value_ptr_ != NULL)

            {

                for (size_t i=0;i<deque_size;++i)

                {

                    new_value_ptr[i] = value_ptr_[(cycdeque_start_+i)%cycdeque_len_];

                }

                delete[] value_ptr_;

                value_ptr_ = NULL;

            }

     

            value_ptr_ = new_value_ptr;

            return true;

        }

     

        //将一个数据放入队列的尾部,如果队列已经满了,你可以将lay_over参数置位true,覆盖原有的数据

        bool push_back(const _value_type &value_data,bool lay_over =false)

        {  

            //

            if((cycdeque_end_ + 1)%cycdeque_len_ ==cycdeque_start_ )

            {

                //如果不要覆盖,返回错误

                if(lay_over == false)

                {

                    return false;

                }

                //如果要覆盖

                else

                {

                    //将最后一个位置覆盖,并且调整起始和结束位置

                    value_ptr_[cycdeque_end_] = value_data;

                    cycdeque_start_ = (cycdeque_start_ +1 ) % cycdeque_len_;

                    cycdeque_end_ = (cycdeque_end_+1) % cycdeque_len_;

                    return true;

                }

            }

            //

            value_ptr_[cycdeque_end_] = value_data;

            cycdeque_end_ = (cycdeque_end_+1) % cycdeque_len_;

            return true;

        }

     

        //从队列的前面得到一个数据

        bool pop_front(_value_type &value_data)

        {

            //

            if (size() == 0)

            {

                return false;

            }

            value_data = value_ptr_[cycdeque_start_];

            cycdeque_start_ = (cycdeque_start_ +1 ) % cycdeque_len_;

            return true;

        }

     

        bool pop_front()

        {

            //

            if (size() == 0)

            {

                return false;

            }

            cycdeque_start_ = (cycdeque_start_ +1 ) % cycdeque_len_;

            return true;

        }

     

        //从队列的前面得到一个数据

        bool pop_end(_value_type &value_data)

        {

            //

            if (size() == 0)

            {

                return false;

            }

     

            cycdeque_end_ = (cycdeque_end_ > 0)?cycdeque_end_-1:cycdeque_len_-1;

            value_data = value_ptr_[cycdeque_end_];

           

            return true;

        }

     

     

        bool pop_end()

        {

            //

            if (size() == 0)

            {

                return false;

            }

            cycdeque_end_ = (cycdeque_end_ > 0)?cycdeque_end_-1:cycdeque_len_-1;

            return true;

        }

       

        //ID不要越界,自己保证,我没兴趣为你干什么

        _value_type& operator[](size_t id)

        {

            return value_ptr_[(cycdeque_start_ + id) % cycdeque_len_];

        }

       

     

        

     

    };

     

    };

     

     

     

    #endif //#ifndef _ZEN_EXTEND_STD_CYC_DEQUE_H_

    本文来自CSDN博客,转载请标明出处:file:///C:/Documents%20and%20Settings/Administrator/桌面/环形缓冲区,魔戒lordrings,boost的circular_buffer%20-%20C++是促进脑死亡的最佳方式%20-%20CSDN博客.mht

  • 相关阅读:
    JS计算每个字符出现的次数
    FCL研究-目录
    FCL研究-LINQ-System.Linq Enumerable
    FCL研究-集合- System.Collections 接口和对象集合
    Vimperator常用快捷键
    【转】WCF光芒下的Web Service
    【转】GridView 加载空行并点击编辑每一个单元格
    [转]在C#程序设计中使用Win32类库
    OpenOffice实现Office转Pdf(支持自定义添加水印、页眉、页脚)
    VUE 动态路由
  • 原文地址:https://www.cnblogs.com/kex1n/p/2286480.html
Copyright © 2011-2022 走看看