Ceph Bufferlist: buffer::ptr的設(shè)計與實現(xiàn)

上一篇文章介紹了raw羊初。

class ptr數(shù)據(jù)結(jié)構(gòu):

  • raw *_raw: 指向?qū)嶋H的數(shù)據(jù)塊
  • _off,_len: 數(shù)據(jù)在raw中的偏移地址,及數(shù)據(jù)長度
  • iterator_impl: 簡易迭代器

迭代器的結(jié)構(gòu)什湘,定義在ptr結(jié)構(gòu)中:

/*
* is_const: 表示是否const類型长赞,const_iterator、iterator
*/
template<bool is_const>
class iterator_impl {
  /*
  * *bp: 指向ptr,ptr構(gòu)造函數(shù)中使用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: 簡易迭代器的定義與實現(xiàn)
    */
    class iterator_impl{...};
    /*資源釋放*/
    void release();
  public:
    /*
    * 定義兩類迭代器
    */
    using const_iterator = iterator_impl<true>;
    using iterator = iterator_impl<false>;
    /*
    * ptr相關(guān)的構(gòu)造函數(shù)
    */
    ptr() : _raw(nullptr), _off(0), _len(0) {}
    /*
    * 使用新的數(shù)據(jù)塊初始化此ptr
    */
    ptr(ceph::unique_leakable_ptr<raw> r);
    /*
    * 創(chuàng)建一個大小為l的數(shù)據(jù)塊禽炬,并初始化此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);
    }

    /*
    * 判斷對齊相關(guān)操作
    */
    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相關(guān)操作
    */
    int get_mempool() const;
    void reassign_to_mempool(int pool);
    void try_assign_to_mempool(int pool);

    /*
    * 數(shù)據(jù)及屬性相關(guān)的操作
    */
    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():

/*
* 資源釋放函數(shù):判斷raw的引用計數(shù)是否有它引:
* 引用計數(shù)為1: 減少引用計數(shù)涧卵,delete raw
* 引用計數(shù)>1: 減少引用計數(shù),_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;
   }
 }
}

構(gòu)造函數(shù)ptr(raw):

/*
* _raw(r.release()): 使用的r的裸指針初始化_raw腹尖,清理unique_leakable_ptr
* 初始化_off, _len
* 初始化raw的引用計數(shù)為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);
}

以下是構(gòu)造及拷貝復(fù)制構(gòu)造函數(shù)的實現(xiàn):

/* 創(chuàng)建大小為l的數(shù)據(jù)塊 */
buffer::ptr::ptr(unsigned l) : _off(0), _len(l)
{
 _raw = buffer::create(l).release();
 _raw->nref.store(1, std::memory_order_release);
}
/* 創(chuàng)建一個新的數(shù)據(jù)塊柳恐,并使用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);
}
/* 拷貝構(gòu)造函數(shù),共享一個數(shù)據(jù)塊 */
buffer::ptr::ptr(const ptr& p) : _raw(p._raw), _off(p._off), _len(p._len)
{
 if (_raw) {
   _raw->nref++;
 }
}
/* 移動拷貝構(gòu)造函數(shù)热幔,清理p的數(shù)據(jù)乐设,數(shù)據(jù)塊的控制權(quán)轉(zhuǎn)移至本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的部分數(shù)據(jù)塊,共享的內(nèi)容: [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++;
}

/* 利用新的數(shù)據(jù)塊初始化ptr绎巨,實際使用數(shù)據(jù)地址與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);
}

/* 賦值構(gòu)造函數(shù)近尚,ptr指向p的數(shù)據(jù)塊,添加引用計數(shù)场勤,釋放本地數(shù)據(jù)塊戈锻,此處代碼考慮了數(shù)據(jù)塊同一個的情況 */
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;
}

/* 移動賦值構(gòu)造函數(shù)歼跟,釋放本地數(shù)據(jù)塊,指向新的數(shù)據(jù)塊 */
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一份本地的數(shù)據(jù)塊數(shù)據(jù) */
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中拷貝數(shù)據(jù)至dest格遭,數(shù)據(jù)范圍為: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比較函數(shù) */
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;
}

/* 判斷內(nèi)容是否為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中拷貝數(shù)據(jù)至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的資源釋放函數(shù),主要釋放ptr_node本身璧微,raw的釋放ptr的析構(gòu)函數(shù)處理
  */
  struct disposer {
    void operator()(ptr_node* const delete_this) {
      if (!dispose_if_hypercombined(delete_this)) {
        delete delete_this;
      }
    }
  };
  /* 默認的析構(gòu)函數(shù) */
  ~ptr_node() = default;

  /*
  * 靜態(tài)函數(shù)作箍,ptr_node的接口函數(shù),使用raw初始化前硫,調(diào)用create_hypercombined函數(shù)
  */
  static std::unique_ptr<ptr_node, disposer> create(ceph::unique_leakable_ptr<raw> r) {
    return create_hypercombined(std::move(r));
  }
  /*
  * 重載函數(shù)胞得,創(chuàng)建長度為l的數(shù)據(jù)塊,buffer::create創(chuàng)建unqiue_ptr 的raw塊开瞭,調(diào)用create_hypercombined
  */
  static std::unique_ptr<ptr_node, disposer> create(const unsigned l) {
    return create_hypercombined(buffer::create(l));
  }

  /*
  * 可變參數(shù)函數(shù)接口懒震,調(diào)用ptr_node構(gòu)造函數(shù)
  */
  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構(gòu)造接口 */
  static ptr_node* copy_hypercombined(const ptr_node& copy_this);

private:
  /*
  * 私有構(gòu)造函數(shù)
  * 可變參數(shù)的構(gòu)造函數(shù)的入口
  */
  template <class... Args>
  ptr_node(Args&&... args) : ptr(std::forward<Args>(args)...) {}
  ptr_node(const ptr_node&) = default;

  /*
  * 禁止ptr的拷貝以及移動拷貝構(gòu)造函數(shù)
  * 禁止ptr_node的賦值及移動賦值構(gòu)造函數(shù)
  * 禁止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方式創(chuàng)建的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創(chuàng)建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);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市嗤详,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瓷炮,老刑警劉巖葱色,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異娘香,居然都是意外死亡苍狰,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門烘绽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來淋昭,“玉大人,你說我怎么就攤上這事安接∠韬觯” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵盏檐,是天一觀的道長歇式。 經(jīng)常有香客問我,道長胡野,這世上最難降的妖魔是什么材失? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮硫豆,結(jié)果婚禮上龙巨,老公的妹妹穿的比我還像新娘笼呆。我一直安慰自己,他們只是感情好旨别,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布诗赌。 她就那樣靜靜地躺著,像睡著了一般昼榛。 火紅的嫁衣襯著肌膚如雪境肾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天胆屿,我揣著相機與錄音奥喻,去河邊找鬼。 笑死非迹,一個胖子當(dāng)著我的面吹牛环鲤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播憎兽,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼冷离,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了纯命?” 一聲冷哼從身側(cè)響起西剥,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎亿汞,沒想到半個月后瞭空,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡疗我,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年咆畏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吴裤。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡旧找,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出麦牺,到底是詐尸還是另有隱情钮蛛,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布枕面,位于F島的核電站愿卒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏潮秘。R本人自食惡果不足惜琼开,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望枕荞。 院中可真熱鬧柜候,春花似錦搞动、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至辅柴,卻和暖如春箩溃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背碌嘀。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工涣旨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人股冗。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓霹陡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親止状。 傳聞我的和親對象是個殘疾皇子烹棉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348