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

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    <=    size

class 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类型的成员函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值