美文网首页
Ceph Bufferlist: buffer::ptr的设计与

Ceph Bufferlist: buffer::ptr的设计与

作者: 圣地亚哥_SVIP | 来源:发表于2020-05-27 16:57 被阅读0次

    上一篇文章介绍了raw

    class ptr数据结构:

    • raw *_raw: 指向实际的数据块
    • _off,_len: 数据在raw中的偏移地址,及数据长度
    • iterator_impl: 简易迭代器

    迭代器的结构,定义在ptr结构中:

    /*
    * is_const: 表示是否const类型,const_iterator、iterator
    */
    template<bool is_const>
    class iterator_impl {
      /*
      * *bp: 指向ptr,ptr构造函数中使用this指针初始化;*bp = ptr
      * *start: 指向bp->c_str()
      */
      const ptr *bp; 
      const char *start; ///< starting pointer into bp->c_str()
      const char *pos;   ///< pointer into bp->c_str()
      const char *end_ptr;   ///< pointer to bp->end_c_str()
      const bool deep;   ///< if true, do not allow shallow ptr copies
    
      iterator_impl(typename std::conditional<is_const, const ptr*, ptr*>::type p,
        size_t offset, bool d)
      : bp(p),
        start(p->c_str() + offset),
        pos(start),
        end_ptr(p->end_c_str()),
        deep(d)
      {}
    
      friend class ptr;
    
    public:
      using pointer = typename std::conditional<is_const, const char*, char *>::type;
      pointer get_pos_add(size_t n) {
        auto r = pos;
        *this += n;
        return r;
      }
      ptr get_ptr(size_t len) {
        if (deep) {
          return buffer::copy(get_pos_add(len), len);
        } else {
          size_t off = pos - bp->c_str();
          *this += len;
          return ptr(*bp, off, len);
        }
      }
    
      iterator_impl& operator+=(size_t len) {
        pos += len;
        if (pos > end_ptr)
          throw end_of_buffer();
              return *this;
      }
    
      const char *get_pos() {
        return pos;
      }
      const char *get_end() {
        return end_ptr;
      }
    
      size_t get_offset() {
        return pos - start;
      }
    
      bool end() const {
        return pos == end_ptr;
      }
    };
    
    class ptr {
        friend class list;
      protected:
        raw *_raw;
        unsigned _off, _len;
      private:
        template<bool is_const>
        /*
        * iterator_impl: 简易迭代器的定义与实现
        */
        class iterator_impl{...};
        /*资源释放*/
        void release();
      public:
        /*
        * 定义两类迭代器
        */
        using const_iterator = iterator_impl<true>;
        using iterator = iterator_impl<false>;
        /*
        * ptr相关的构造函数
        */
        ptr() : _raw(nullptr), _off(0), _len(0) {}
        /*
        * 使用新的数据块初始化此ptr
        */
        ptr(ceph::unique_leakable_ptr<raw> r);
        /*
        * 创建一个大小为l的数据块,并初始化此ptr
        */
        ptr(unsigned l);
        ptr(const char *d, unsigned l);
        ptr(const ptr& p);
        ptr(ptr&& p) noexcept;
        ptr(const ptr& p, unsigned o, unsigned l);
        ptr(const ptr& p, ceph::unique_leakable_ptr<raw> r);
        ptr& operator= (const ptr& p);
        ptr& operator= (ptr&& p) noexcept;
        ~ptr() {
          release();
        }
    
        bool have_raw() const { return _raw ? true:false; }
    
        ceph::unique_leakable_ptr<raw> clone();
        void swap(ptr& other) noexcept;
    
        /*
        * 返回迭代器
        */
        iterator begin(size_t offset=0) {
          return iterator(this, offset, false);
        }
        const_iterator begin(size_t offset=0) const {
          return const_iterator(this, offset, false);
        }
        const_iterator cbegin() const {
          return begin();
        }
        const_iterator begin_deep(size_t offset=0) const {
          return const_iterator(this, offset, true);
        }
    
        /*
        * 判断对齐相关操作
        */
        bool is_aligned(unsigned align) const {
          return ((long)c_str() & (align-1)) == 0;
        }
        bool is_page_aligned() const { return is_aligned(CEPH_PAGE_SIZE); }
        bool is_n_align_sized(unsigned align) const
        {
          return (length() % align) == 0;
        }
        bool is_n_page_sized() const { return is_n_align_sized(CEPH_PAGE_SIZE); }
        bool is_partial() const {
          return have_raw() && (start() > 0 || end() < raw_length());
        }
        /*
        * mempool相关操作
        */
        int get_mempool() const;
        void reassign_to_mempool(int pool);
        void try_assign_to_mempool(int pool);
    
        /*
        * 数据及属性相关的操作
        */
        const char *c_str() const{
          assert(_raw);
          return _raw->get_data() + _off;
        }
        char *c_str(){
          assert(_raw);
          return _raw->get_data() + _off;
        }
        const char *end_c_str() const{
          assert(_raw);
          return _raw->get_data() + _off + _len;
        }
        char *end_c_str(){assert(_raw);return _raw->get_data() + _off + _len;}
        unsigned length() const { return _len; }
        unsigned offset() const { return _off; }
        unsigned start() const { return _off; }
        unsigned end() const { return _off + _len; }
        /* raw尾部剩余空间 */
        unsigned unused_tail_length() const{
        {
          if (_raw)
            return _raw->len - (_off+_len);
          else
            return 0;
        }
        const char& operator[](unsigned n) const{return _raw->get_data()[_off + n];}
        char& operator[](unsigned n){return _raw->get_data()[_off + n];}
    
        const char *raw_c_str() const{return _raw->data;}
        unsigned raw_length() const{return _raw->len;}
        int raw_nref() const{return _raw->nref; }
    
        void copy_out(unsigned o, unsigned l, char *dest) const;
    
        unsigned wasted() const;
    
        int cmp(const ptr& o) const;
        bool is_zero() const;
    
        // modifiers
        void set_offset(unsigned o) {
          assert(raw_length() >= o);
          _off = o;
        }
        void set_length(unsigned l) {
          assert(raw_length() >= l);
          _len = l;
        }
    
        unsigned append(char c);
        unsigned append(const char *p, unsigned l);
        inline unsigned append(std::string_view s) {
          return append(s.data(), s.length());
        }
        void copy_in(unsigned o, unsigned l, const char *src, bool crc_reset = true);
        void zero(bool crc_reset = true);
        void zero(unsigned o, unsigned l, bool crc_reset = true);
        unsigned append_zeros(unsigned l);
    
      };
    

    release():

    /*
    * 资源释放函数:判断raw的引用计数是否有它引:
    * 引用计数为1: 减少引用计数,delete raw
    * 引用计数>1: 减少引用计数,_raw = nullptr;
    */
    void ptr::release(){
     if (_raw) {
       const bool last_one = (1 == _raw->nref.load(std::memory_order_acquire));
       if (likely(last_one) || --_raw->nref == 0) {
         const auto* delete_raw = _raw;
         _raw = nullptr;
         delete delete_raw; 
       } else {
         _raw = nullptr;
       }
     }
    }
    

    构造函数ptr(raw):

    /*
    * _raw(r.release()): 使用的r的裸指针初始化_raw,清理unique_leakable_ptr
    * 初始化_off, _len
    * 初始化raw的引用计数为1
    */
    ptr::ptr(ceph::unique_leakable_ptr<raw> r)
      : _raw(r.release()),
        _off(0),
        _len(_raw->len)
    {
      _raw->nref.store(1, std::memory_order_release);
    }
    

    以下是构造及拷贝复制构造函数的实现:

    /* 创建大小为l的数据块 */
    buffer::ptr::ptr(unsigned l) : _off(0), _len(l)
    {
     _raw = buffer::create(l).release();
     _raw->nref.store(1, std::memory_order_release);
    }
    /* 创建一个新的数据块,并使用d初始化 */
    buffer::ptr::ptr(const char *d, unsigned l) : _off(0), _len(l) 
    {
     _raw = buffer::copy(d, l).release();
     _raw->nref.store(1, std::memory_order_release);
    }
    /* 拷贝构造函数,共享一个数据块 */
    buffer::ptr::ptr(const ptr& p) : _raw(p._raw), _off(p._off), _len(p._len)
    {
     if (_raw) {
       _raw->nref++;
     }
    }
    /* 移动拷贝构造函数,清理p的数据,数据块的控制权转移至本ptr */
    buffer::ptr::ptr(ptr&& p) noexcept : _raw(p._raw), _off(p._off), _len(p._len)
    {
     p._raw = nullptr;
     p._off = p._len = 0;
    }
    /* 共享p的部分数据块,共享的内容: [p._off+o,l] */
    buffer::ptr::ptr(const ptr& p, unsigned o, unsigned l)
     : _raw(p._raw), _off(p._off + o), _len(l)
    {
     assert(o+l <= p._len);
     assert(_raw);
     _raw->nref++;
    }
    
    /* 利用新的数据块初始化ptr,实际使用数据地址与p相同 */
    buffer::ptr::ptr(const ptr& p, ceph::unique_leakable_ptr<raw> r)
     : _raw(r.release()),
       _off(p._off),
       _len(p._len)
    {
     _raw->nref.store(1, std::memory_order_release);
    }
    
    /* 赋值构造函数,ptr指向p的数据块,添加引用计数,释放本地数据块,此处代码考虑了数据块同一个的情况 */
    buffer::ptr& buffer::ptr::operator= (const ptr& p)
    {
     if (p._raw) {
       p._raw->nref++;
     }
     buffer::raw *raw = p._raw; 
     release();
     if (raw) {
       _raw = raw;
       _off = p._off;
       _len = p._len;
     } else {
       _off = _len = 0;
     }
     return *this;
    }
    
    /* 移动赋值构造函数,释放本地数据块,指向新的数据块 */
    buffer::ptr& buffer::ptr::operator= (ptr&& p) noexcept
    {
     release();
     buffer::raw *raw = p._raw;
     if (raw) {
       _raw = raw;
       _off = p._off;
       _len = p._len;
       p._raw = nullptr;
       p._off = p._len = 0;
     } else {
       _off = _len = 0;
     }
     return *this;
    }
    
    /* clone一份本地的数据块数据 */
    ceph::unique_leakable_ptr<buffer::raw> buffer::ptr::clone()
    {
     return _raw->clone();
    }
    
    /* 交换ptr */
    void buffer::ptr::swap(ptr& other) noexcept
    {
     raw *r = _raw;
     unsigned o = _off;
     unsigned l = _len;
     _raw = other._raw;
     _off = other._off;
     _len = other._len;
     other._raw = r;
     other._off = o;
     other._len = l;
    }
    
    /* 从ptr中拷贝数据至dest,数据范围为:start: _off+o, Len: l */
    void buffer::ptr::copy_out(unsigned o, unsigned l, char *dest) const {
     assert(_raw);
     if (o+l > _len)
         throw end_of_buffer();
     char* src =  _raw->data + _off + o;
     maybe_inline_memcpy(dest, src, l, 8);
    }
    /* 未被此ptr使用的空间大小 */
    unsigned buffer::ptr::wasted() const
    {
     return _raw->len - _len;
    }
    
    /* ptr比较函数 */
    int buffer::ptr::cmp(const ptr& o) const
    {
     int l = _len < o._len ? _len : o._len;
     if (l) {
       int r = memcmp(c_str(), o.c_str(), l);
       if (r)
    return r;
     }
     if (_len < o._len)
       return -1;
     if (_len > o._len)
       return 1;
     return 0;
    }
    
    /* 判断内容是否为0 */
    bool buffer::ptr::is_zero() const
    {
     return mem_is_zero(c_str(), _len);
    }
    
    /* 
    * ptr append一个字符 
    * 注:append的所有操作,末尾追加,使用unused_tail_length,不改变raw实际大小
    */
    unsigned buffer::ptr::append(char c)
    {
     assert(_raw);
     assert(1 <= unused_tail_length());
     char* ptr = _raw->data + _off + _len;
     *ptr = c;
     _len++;
     return _len + _off;
    }
    
    unsigned buffer::ptr::append(const char *p, unsigned l)
    {
     assert(_raw);
     assert(l <= unused_tail_length());
     char* c = _raw->data + _off + _len;
     maybe_inline_memcpy(c, p, l, 32);
     _len += l;
     return _len + _off;
    }
    
    unsigned buffer::ptr::append_zeros(unsigned l)
    {
     assert(_raw);
     assert(l <= unused_tail_length());
     char* c = _raw->data + _off + _len;
     // FIPS zeroization audit 20191115: this memset is not security related.
     memset(c, 0, l);
     _len += l;
     return _len + _off;
    }
    
    /*
    * 从src中拷贝数据至raw
    */
    void buffer::ptr::copy_in(unsigned o, unsigned l, const char *src, bool crc_reset)
    {
     assert(_raw);
     assert(o <= _len);
     assert(o+l <= _len);
     char* dest = _raw->data + _off + o;
     if (crc_reset)
         _raw->invalidate_crc();
     maybe_inline_memcpy(dest, src, l, 64);
    }
    /*
    * 重置动作
    */
    void buffer::ptr::zero(bool crc_reset)
    {
     if (crc_reset)
         _raw->invalidate_crc();
     // FIPS zeroization audit 20191115: this memset is not security related.
     memset(c_str(), 0, _len);
    }
    
    void buffer::ptr::zero(unsigned o, unsigned l, bool crc_reset)
    {
     assert(o+l <= _len);
     if (crc_reset)
         _raw->invalidate_crc();
     // FIPS zeroization audit 20191115: this memset is not security related.
     memset(c_str()+o, 0, l);
    }
    

    ptr_hook
    用于连接ptr_node:

    struct ptr_hook {
      mutable ptr_hook* next;
    
      ptr_hook() = default;
      ptr_hook(ptr_hook* const next)
        : next(next) {
      }
    };
    

    ptr_node:
    ptr_node的定义:

    /*
    * 继承ptr_hook:主要用于buffer::list中,next链表
    */
    class ptr_node : public ptr_hook, public ptr {
    public:
      struct cloner {
        ptr_node* operator()(const ptr_node& clone_this);
      };
      /*
      * 自定义unique_ptr的资源释放函数,主要释放ptr_node本身,raw的释放ptr的析构函数处理
      */
      struct disposer {
        void operator()(ptr_node* const delete_this) {
          if (!dispose_if_hypercombined(delete_this)) {
            delete delete_this;
          }
        }
      };
      /* 默认的析构函数 */
      ~ptr_node() = default;
    
      /*
      * 静态函数,ptr_node的接口函数,使用raw初始化,调用create_hypercombined函数
      */
      static std::unique_ptr<ptr_node, disposer> create(ceph::unique_leakable_ptr<raw> r) {
        return create_hypercombined(std::move(r));
      }
      /*
      * 重载函数,创建长度为l的数据块,buffer::create创建unqiue_ptr 的raw块,调用create_hypercombined
      */
      static std::unique_ptr<ptr_node, disposer> create(const unsigned l) {
        return create_hypercombined(buffer::create(l));
      }
    
      /*
      * 可变参数函数接口,调用ptr_node构造函数
      */
      template <class... Args>
      static std::unique_ptr<ptr_node, disposer> create(Args&&... args) {
        return std::unique_ptr<ptr_node, disposer>(new ptr_node(std::forward<Args>(args)...));
      }
      /* ptr_node构造接口 */
      static ptr_node* copy_hypercombined(const ptr_node& copy_this);
    
    private:
      /*
      * 私有构造函数
      * 可变参数的构造函数的入口
      */
      template <class... Args>
      ptr_node(Args&&... args) : ptr(std::forward<Args>(args)...) {}
      ptr_node(const ptr_node&) = default;
    
      /*
      * 禁止ptr的拷贝以及移动拷贝构造函数
      * 禁止ptr_node的赋值及移动赋值构造函数
      * 禁止swap功能
      */
      ptr& operator= (const ptr& p) = delete;
      ptr& operator= (ptr&& p) noexcept = delete;
      ptr_node& operator= (const ptr_node& p) = delete;
      ptr_node& operator= (ptr_node&& p) noexcept = delete;
      void swap(ptr& other) noexcept = delete;
      void swap(ptr_node& other) noexcept = delete;
    
      /*
      * 判断是否使用hypercombined
      */
      static bool dispose_if_hypercombined(ptr_node* delete_this);
      static std::unique_ptr<ptr_node, disposer> create_hypercombined(ceph::unique_leakable_ptr<raw> r);
    };
    
    /*
    * 判断是否使用hypercombined方式创建的raw
    */
    bool buffer::ptr_node::dispose_if_hypercombined(buffer::ptr_node* const delete_this)
    {
      const bool is_hypercombined = static_cast<void*>(delete_this) == \
        static_cast<void*>(&delete_this->_raw->bptr_storage);
      if (is_hypercombined) {
        delete_this->~ptr_node();
      }
      return is_hypercombined;
    }
    
    /*
    * 基于raw创建ptr_node
    */
    std::unique_ptr<buffer::ptr_node, buffer::ptr_node::disposer> buffer::ptr_node::create_hypercombined(ceph::unique_leakable_ptr<buffer::raw> r)
    {
      return std::unique_ptr<buffer::ptr_node, buffer::ptr_node::disposer>(new ptr_node(std::move(r)));
    }
    
    /*
    * clone ptr_node
    */
    buffer::ptr_node* buffer::ptr_node::cloner::operator()(
      const buffer::ptr_node& clone_this)
    {
      return new ptr_node(clone_this);
    }
    

    相关文章

      网友评论

          本文标题:Ceph Bufferlist: buffer::ptr的设计与

          本文链接:https://www.haomeiwen.com/subject/kyxgahtx.html