ISE -- I/O Buffer 之 STL vector学习

来源:互联网 发布:大数据云计算考研 编辑:程序博客网 时间:2024/06/08 15:31

0x01 缘起

       在高性能服务器开发的过程中,良好的IO缓存是整个设计比较重要的环节。带着这方面的兴趣,阅读了开源ISE的IO Buffer设计,不评估其优劣,纯粹学习这方面知识,深度学习下STL vector容器的使用和内存的管理。

0x02 IO Buffer介绍

      消息缓存,主要存储socket接收和发送的消息。发送消息时,将消息有序的缓存到buffer中;消息接收时,将消息存放在缓存中,进行拼包,还原出完整的消息。

0x03 ISE IO Buffer

///////////////////////////////////////////////////////////////////////////////// class IoBuffer - 输入输出缓存//// +-----------------+------------------+------------------+// |  useless bytes  |  readable bytes  |  writable bytes  |// |                 |     (CONTENT)    |                  |// +-----------------+------------------+------------------+// |                 |                  |                  |// 0     <=     readerIndex   <=   writerIndex    <=    sizeclass IoBuffer{public:    enum { INITIAL_SIZE = 1024 }; //Buffer初始化大小public:    IoBuffer();    ~IoBuffer();    /* const 成员函数,不能修改类成员;     * 获取可以读的有效字节;     * */    int getReadableBytes() const { return writerIndex_ - readerIndex_; }    /*     * 获取可以写的有效空间字节数;     * */    int getWritableBytes() const { return (int)buffer_.size() - writerIndex_; }    /*     * 获取可以目前已经读取完,认为无效的空间字节数;     * */    int getUselessBytes() const { return readerIndex_; }    /*     * 追加一个字符串对象到缓存;     * */    void append(const string& str);    /*     * 追加一个指针对象 bytes个字节到缓存;     * */    void append(const void *data, int bytes);    /*     * 向缓存追加 bytes 个字节并填充为'\0';     * */    void append(int bytes);    /*从缓存读取 bytes 个字节数据*/    void retrieve(int bytes);    /*从缓存读取全部可读数据并存入 str 中*/    void retrieveAll(string& str);    /*从缓存读取全部可读数据,相当于清空*/    void retrieveAll();    /*交换一个IO缓存*/    void swap(IoBuffer& rhs);    /* 获取读的起始指针 ,访问一个只读指针 */    const char* peek() const { return getBufferPtr() + readerIndex_; }private:    /* 获取缓存的起始指针 */    char* getBufferPtr() const { return (char*)&*buffer_.begin(); }    /* 获取写位置的起始指针 */    char* getWriterPtr() const { return getBufferPtr() + writerIndex_; }    /* 扩展缓存  */    void makeSpace(int moreBytes);private:    std::vector<char> buffer_; //buffer 缓存容器,内存的扩展    int readerIndex_; //读指针    int writerIndex_; //写指针};
关键代码段,内存扩展:
//-----------------------------------------------------------------------------// 描述: 扩展缓存空间以便可再写进 moreBytes 个字节//-----------------------------------------------------------------------------void IoBuffer::makeSpace(int moreBytes){/*如果无用的字节空间和可以写的字节空间小于需要写入的空间,就调用resize调整扩大 * vector容量,满足值的写入; * vector容量会成倍扩张,INITIAL_SIZE*2, * 并将原来的从就的地方拷贝到新的;*/    if (getWritableBytes() + getUselessBytes() < moreBytes)    {        buffer_.resize(writerIndex_ + moreBytes);    }    else    {        /*如果大于,调整目前的位置,将内存移动一次,将全部可读数据移至缓存开始处*/        int readableBytes = getReadableBytes();        char *buffer = getBufferPtr();        memmove(buffer, buffer + readerIndex_, readableBytes);        readerIndex_ = 0;        writerIndex_ = readerIndex_ + readableBytes;        ISE_ASSERT(readableBytes == getReadableBytes());    }}
后面将详细讲解vector扩容等知识点。

0x04 STL vector

类关键片段:

// 默认allocator为alloc, 其具体使用版本请参照<stl_alloc.h>    template <class T, class Alloc = alloc>    class vector    {    public:      // 标记为'STL标准强制要求'的typedefs用于提供iterator_traits<I>支持      typedef T value_type;                         // STL标准强制要求      typedef value_type* pointer;                  // STL标准强制要求      typedef const value_type* const_pointer;      // 由于vector的特性, 一般我们实作的时候都分配给其连续的内存空间,      // 所以其迭代器只需要定义成原生指针即可满足需要      typedef value_type* iterator;                 // STL标准强制要求      typedef const value_type* const_iterator;      typedef value_type& reference;                // STL标准强制要求      typedef const value_type& const_reference;      typedef size_t size_type;      typedef ptrdiff_t difference_type;            // STL标准强制要求        #ifdef __STL_CLASS_PARTIAL_SPECIALIZATION      typedef reverse_iterator<const_iterator> const_reverse_iterator;      typedef reverse_iterator<iterator> reverse_iterator;    #else /* __STL_CLASS_PARTIAL_SPECIALIZATION */      typedef reverse_iterator<const_iterator, value_type, const_reference,                               difference_type>  const_reverse_iterator;      typedef reverse_iterator<iterator, value_type, reference, difference_type>              reverse_iterator;    #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */        protected:      // 这个提供STL标准的allocator接口      typedef simple_alloc<value_type, Alloc> data_allocator;          iterator start;               // 内存空间起始点      iterator finish;              // 当前使用的内存空间结束点      iterator end_of_storage;      // 实际分配内存空间的结束点          void insert_aux(iterator position, const T& x);   ....................  }
详细讲解resize函数:
  void resize(size_type __new_size, const _Tp& __x) {    if (__new_size < size())       erase(begin() + __new_size, end());    else      insert(end(), __new_size - size(), __x);  }  void resize(size_type __new_size) { resize(__new_size, _Tp()); }

resize()的作用是改变vector中元素的数目:
    1、如果n比当前的vector元素数目要小,vector的容量要缩减到resize的第一个参数大小,既n。并移除那些超出n的元素同时销毁他们。
    2、如果n比当前vector元素数目要大,在vector的末尾扩展需要的元素数目,如果第二个参数val指定了,扩展的新元素初始化为val的副本,否则按类型默认初始化。
    注意:如果n大于当前的vector的容量(是容量,并非vector的size),将会引起自动内存分配。所以现有的pointer,references,iterators将会失效。

0x05 额外补充const

        1、const成员函数不允许修改它所在对象的任何一个数据成员,const成员函数能够访问对象的const成员,而其他成员函数则不可以。
        2、对于const类对象/指针/引用可以调用const成员函数,但是不可以调用非const类型的成员函数

原创粉丝点击