zoukankan      html  css  js  c++  java
  • SharedPtrControlBlock

    template <typename T> class shared_ptr;
    template <typename T> class weak_ptr;
     
    // This class is an internal implementation detail for shared_ptr.
    class SharedPtrControlBlock {
      template <typename T> friend class shared_ptr;
      template <typename T> friend class weak_ptr;
     private:
      SharedPtrControlBlock() : refcount_(1), weak_count_(1) { }
      int refcount_;
      int weak_count_;
    };
     
    // NOTE: It is strongly encouraged to use scoped_ptr if you could.
    //       shared_ptr should be only used at the cases that
    //       there is no clear owner for the object, anyone reference the object
    //       may need take care if the object should be deleted.
    // NOTE: Don't use this class to replace boost::shared_ptr when working with
    //       thrift.
    template <typename T>
    class shared_ptr {
      template <typename U> friend class weak_ptr;
     public:
      typedef T element_type;
     
      explicit shared_ptr(T* ptr = NULL)
          : ptr_(ptr),
            control_block_(ptr != NULL ? new SharedPtrControlBlock : NULL) {
      }
     
      // Copy constructor: makes this object a copy of ptr
      template <typename U>
      shared_ptr(const shared_ptr<U>& ptr)  // NOLINT
          : ptr_(NULL),
            control_block_(NULL) {
        Initialize(ptr);
      }
      // Need non-templated version to prevent the compiler-generated default
      shared_ptr(const shared_ptr<T>& ptr)  // NOLINT
          : ptr_(NULL),
            control_block_(NULL) {
        Initialize(ptr);
      }
     
      // Assignment operator. Replaces the existing shared_ptr with ptr.
      template <typename U>
      shared_ptr<T>& operator=(const shared_ptr<U>& ptr) {
        if (ptr_ != ptr.ptr_) {
          shared_ptr<T> me(ptr);   // will hold our previous state to be destroyed.
          swap(me);
        }
        return *this;
      }
     
      // Need non-templated version to prevent the compiler-generated default
      shared_ptr<T>& operator=(const shared_ptr<T>& ptr) {
        if (ptr_ != ptr.ptr_) {
          shared_ptr<T> me(ptr);   // will hold our previous state to be destroyed.
          swap(me);
        }
        return *this;
      }
     
      ~shared_ptr() {
        if (ptr_ != NULL) {
          if (AtomicDecrement(&control_block_->refcount_) == 0) {
            delete ptr_;
     
            // weak_count_ is defined as the number of weak_ptrs that observe
            // ptr_, plus 1 if refcount_ is nonzero.
            if (AtomicDecrement(&control_block_->weak_count_) == 0) {
              delete control_block_;
            }
          }
        }
      }
     
      // Replaces underlying raw pointer with the one passed in.  The reference
      // count is set to one (or zero if the pointer is NULL) for the pointer
      // being passed in and decremented for the one being replaced.
      void reset(T* p = NULL) {
        if (p != ptr_) {
          shared_ptr<T> tmp(p);
          tmp.swap(*this);
        }
      }
     
      // Exchanges the contents of this with the contents of r.  This function
      // supports more efficient swapping since it eliminates the need for a
      // temporary shared_ptr object.
      void swap(shared_ptr<T>& r) {
        std::swap(ptr_, r.ptr_);
        std::swap(control_block_, r.control_block_);
      }
     
      // The following function is useful for gaining access to the underlying
      // pointer when a shared_ptr remains in scope so the reference-count is
      // known to be > 0 (e.g. for parameter passing).
      T* get() const {
        return ptr_;
      }
     
      T& operator*() const {
        return *ptr_;
      }
     
      T* operator->() const {
        return ptr_;
      }
     
      int use_count() const {
        return control_block_ ? control_block_->refcount_ : 1;
      }
     
      bool unique() const {
        return use_count() == 1;
      }
     
     private:
      // If r is non-empty, initialize *this to share ownership with r,
      // increasing the underlying reference count.
      // If r is empty, *this remains empty.
      // Requires: this is empty, namely this->ptr_ == NULL.
      template <typename U>
      void Initialize(const shared_ptr<U>& r) {
        if (r.control_block_ != NULL) {
          AtomicIncrement(&r.control_block_->refcount_);
     
          ptr_ = r.ptr_;
          control_block_ = r.control_block_;
        }
      }
     
      T* ptr_;
      SharedPtrControlBlock* control_block_;
     
      template <typename U>
      friend class shared_ptr;
    };
     
    // Matches the interface of std::swap as an aid to generic programming.
    template <typename T> void swap(shared_ptr<T>& r, shared_ptr<T>& s) {
      r.swap(s);
    }
     
    // Weak ptrs:
    //   The weak_ptr auxiliary class is used to break ownership cycles. A weak_ptr
    //   points to an object that's owned by a shared_ptr, but the weak_ptr is an
    //   observer, not an owner. When the last shared_ptr that points to the object
    //   disappear, the weak_ptr expires, at which point the expired() member
    //   function will return true.
    //   You can't directly get a raw pointer from weak_ptr, to access a weak_ptr's
    //   pointed-to object, use lock() to obtain a temporary shared_ptr.
    //   See the draft C++ standard (as of October 2007 the latest draft is N2461)
    //   for the detailed specification.
    template <typename T>
    class weak_ptr {
      template <typename U> friend class weak_ptr;
     public:
      typedef T element_type;
     
      // Create an empty (i.e. already expired) weak_ptr.
      weak_ptr() : ptr_(NULL), control_block_(NULL) { }
     
      // Create a weak_ptr that observes the same object that ptr points
      // to.  Note that there is no race condition here: we know that the
      // control block can't disappear while we're looking at it because
      // it is owned by at least one shared_ptr, ptr.
      template <typename U> weak_ptr(const shared_ptr<U>& ptr) {
        CopyFrom(ptr.ptr_, ptr.control_block_);
      }
     
      // Copy a weak_ptr. The object it points to might disappear, but we
      // don't care: we're only working with the control block, and it can't
      // disappear while we're looking at because it's owned by at least one
      // weak_ptr, ptr.
      template <typename U> weak_ptr(const weak_ptr<U>& ptr) {
        CopyFrom(ptr.ptr_, ptr.control_block_);
      }
     
      // Need non-templated version to prevent default copy constructor
      weak_ptr(const weak_ptr& ptr) {
        CopyFrom(ptr.ptr_, ptr.control_block_);
      }
     
      // Destroy the weak_ptr. If no shared_ptr owns the control block, and if
      // we are the last weak_ptr to own it, then it can be deleted. Note that
      // weak_count_ is defined as the number of weak_ptrs sharing this control
      // block, plus 1 if there are any shared_ptrs. We therefore know that it's
      // safe to delete the control block when weak_count_ reaches 0, without
      // having to perform any additional tests.
      ~weak_ptr() {
        if (control_block_ != NULL &&
            (AtomicDecrement(&control_block_->weak_count_) == 0)) {
          delete control_block_;
        }
      }
     
      weak_ptr& operator=(const weak_ptr& ptr) {
        if (&ptr != this) {
          weak_ptr tmp(ptr);
          tmp.swap(*this);
        }
        return *this;
      }
      template <typename U> weak_ptr& operator=(const weak_ptr<U>& ptr) {
        weak_ptr tmp(ptr);
        tmp.swap(*this);
        return *this;
      }
      template <typename U> weak_ptr& operator=(const shared_ptr<U>& ptr) {
        weak_ptr tmp(ptr);
        tmp.swap(*this);
        return *this;
      }
     
      void swap(weak_ptr& ptr) {
        swap_weak_ptr(ptr_, ptr.ptr_);
        swap_weak_ptr(control_block_, ptr.control_block_);
      }
     
      void reset() {
        weak_ptr tmp;
        tmp.swap(*this);
      }
     
      // Return the number of shared_ptrs that own the object we are observing.
      // Note that this number can be 0 (if this pointer has expired).
      int use_count() const {
        return control_block_ != NULL ? control_block_->refcount_ : 0;
      }
     
      bool expired() const { return use_count() == 0; }
     
     private:
      void CopyFrom(T* ptr, SharedPtrControlBlock* control_block) {
        ptr_ = ptr;
        control_block_ = control_block;
        if (control_block_ != NULL)
          AtomicIncrement(&control_block_->weak_count_);
      }
     
     private:
      element_type* ptr_;
      SharedPtrControlBlock* control_block_;
    };
     
    template <typename T> void swap_weak_ptr(weak_ptr<T>& r, weak_ptr<T>& s) {
      r.swap(s);
    }

  • 相关阅读:
    关于C 语言的字符串常量拼接
    网络处理器简介
    杨先生的博客目录(持续更新......)
    搭建json-server服务
    Spring boot + Mybatis + SQLite 搭建blog API
    使用json-server POST 数据结果只有id
    解决python查询数据库字段为decimal类型的数据结果为科学计数法的问题
    Maven仓库安装配置及使用
    Jekins发送Allure测试报告邮件
    Jenkins发送邮件配置
  • 原文地址:https://www.cnblogs.com/yzy6806555/p/4121958.html
Copyright © 2011-2022 走看看