tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

scoped_refptr.h (12831B)


      1 // Copyright 2017 The Chromium Authors
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_MEMORY_SCOPED_REFPTR_H_
      6 #define BASE_MEMORY_SCOPED_REFPTR_H_
      7 
      8 #include <stddef.h>
      9 
     10 #include <iosfwd>
     11 #include <type_traits>
     12 #include <utility>
     13 
     14 #include "base/check.h"
     15 #include "base/compiler_specific.h"
     16 #include "base/memory/raw_ptr_exclusion.h"
     17 
     18 template <class T>
     19 class scoped_refptr;
     20 
     21 namespace base {
     22 
     23 template <class, typename>
     24 class RefCounted;
     25 template <class, typename>
     26 class RefCountedThreadSafe;
     27 template <class>
     28 class RefCountedDeleteOnSequence;
     29 class SequencedTaskRunner;
     30 
     31 template <typename T>
     32 scoped_refptr<T> AdoptRef(T* t);
     33 
     34 namespace subtle {
     35 
     36 enum AdoptRefTag { kAdoptRefTag };
     37 enum StartRefCountFromZeroTag { kStartRefCountFromZeroTag };
     38 enum StartRefCountFromOneTag { kStartRefCountFromOneTag };
     39 
     40 template <typename TagType>
     41 struct RefCountPreferenceTagTraits;
     42 
     43 template <>
     44 struct RefCountPreferenceTagTraits<StartRefCountFromZeroTag> {
     45  static constexpr StartRefCountFromZeroTag kTag = kStartRefCountFromZeroTag;
     46 };
     47 
     48 template <>
     49 struct RefCountPreferenceTagTraits<StartRefCountFromOneTag> {
     50  static constexpr StartRefCountFromOneTag kTag = kStartRefCountFromOneTag;
     51 };
     52 
     53 template <typename T, typename Tag = typename T::RefCountPreferenceTag>
     54 constexpr Tag GetRefCountPreference() {
     55  return RefCountPreferenceTagTraits<Tag>::kTag;
     56 }
     57 
     58 // scoped_refptr<T> is typically used with one of several RefCounted<T> base
     59 // classes or with custom AddRef and Release methods. These overloads dispatch
     60 // on which was used.
     61 
     62 template <typename T, typename U, typename V>
     63 constexpr bool IsRefCountPreferenceOverridden(const T*,
     64                                              const RefCounted<U, V>*) {
     65  return !std::is_same_v<std::decay_t<decltype(GetRefCountPreference<T>())>,
     66                         std::decay_t<decltype(GetRefCountPreference<U>())>>;
     67 }
     68 
     69 template <typename T, typename U, typename V>
     70 constexpr bool IsRefCountPreferenceOverridden(
     71    const T*,
     72    const RefCountedThreadSafe<U, V>*) {
     73  return !std::is_same_v<std::decay_t<decltype(GetRefCountPreference<T>())>,
     74                         std::decay_t<decltype(GetRefCountPreference<U>())>>;
     75 }
     76 
     77 template <typename T, typename U>
     78 constexpr bool IsRefCountPreferenceOverridden(
     79    const T*,
     80    const RefCountedDeleteOnSequence<U>*) {
     81  return !std::is_same_v<std::decay_t<decltype(GetRefCountPreference<T>())>,
     82                         std::decay_t<decltype(GetRefCountPreference<U>())>>;
     83 }
     84 
     85 constexpr bool IsRefCountPreferenceOverridden(...) {
     86  return false;
     87 }
     88 
     89 template <typename T, typename U, typename V>
     90 constexpr void AssertRefCountBaseMatches(const T*, const RefCounted<U, V>*) {
     91  static_assert(std::is_base_of_v<U, T>,
     92                "T implements RefCounted<U>, but U is not a base of T.");
     93 }
     94 
     95 template <typename T, typename U, typename V>
     96 constexpr void AssertRefCountBaseMatches(const T*,
     97                                         const RefCountedThreadSafe<U, V>*) {
     98  static_assert(
     99      std::is_base_of_v<U, T>,
    100      "T implements RefCountedThreadSafe<U>, but U is not a base of T.");
    101 }
    102 
    103 template <typename T, typename U>
    104 constexpr void AssertRefCountBaseMatches(const T*,
    105                                         const RefCountedDeleteOnSequence<U>*) {
    106  static_assert(
    107      std::is_base_of_v<U, T>,
    108      "T implements RefCountedDeleteOnSequence<U>, but U is not a base of T.");
    109 }
    110 
    111 constexpr void AssertRefCountBaseMatches(...) {}
    112 
    113 }  // namespace subtle
    114 
    115 // Creates a scoped_refptr from a raw pointer without incrementing the reference
    116 // count. Use this only for a newly created object whose reference count starts
    117 // from 1 instead of 0.
    118 template <typename T>
    119 scoped_refptr<T> AdoptRef(T* obj) {
    120  using Tag = std::decay_t<decltype(subtle::GetRefCountPreference<T>())>;
    121  static_assert(std::is_same_v<subtle::StartRefCountFromOneTag, Tag>,
    122                "Use AdoptRef only if the reference count starts from one.");
    123 
    124  DCHECK(obj);
    125  DCHECK(obj->HasOneRef());
    126  obj->Adopted();
    127  return scoped_refptr<T>(obj, subtle::kAdoptRefTag);
    128 }
    129 
    130 namespace subtle {
    131 
    132 template <typename T>
    133 scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromZeroTag) {
    134  return scoped_refptr<T>(obj);
    135 }
    136 
    137 template <typename T>
    138 scoped_refptr<T> AdoptRefIfNeeded(T* obj, StartRefCountFromOneTag) {
    139  return AdoptRef(obj);
    140 }
    141 
    142 }  // namespace subtle
    143 
    144 // Constructs an instance of T, which is a ref counted type, and wraps the
    145 // object into a scoped_refptr<T>.
    146 template <typename T, typename... Args>
    147 scoped_refptr<T> MakeRefCounted(Args&&... args) {
    148  T* obj = new T(std::forward<Args>(args)...);
    149  return subtle::AdoptRefIfNeeded(obj, subtle::GetRefCountPreference<T>());
    150 }
    151 
    152 // Takes an instance of T, which is a ref counted type, and wraps the object
    153 // into a scoped_refptr<T>.
    154 template <typename T>
    155 scoped_refptr<T> WrapRefCounted(T* t) {
    156  return scoped_refptr<T>(t);
    157 }
    158 
    159 }  // namespace base
    160 
    161 //
    162 // A smart pointer class for reference counted objects.  Use this class instead
    163 // of calling AddRef and Release manually on a reference counted object to
    164 // avoid common memory leaks caused by forgetting to Release an object
    165 // reference.  Sample usage:
    166 //
    167 //   class MyFoo : public RefCounted<MyFoo> {
    168 //    ...
    169 //    private:
    170 //     friend class RefCounted<MyFoo>;  // Allow destruction by RefCounted<>.
    171 //     ~MyFoo();                        // Destructor must be private/protected.
    172 //   };
    173 //
    174 //   void some_function() {
    175 //     scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>();
    176 //     foo->Method(param);
    177 //     // |foo| is released when this function returns
    178 //   }
    179 //
    180 //   void some_other_function() {
    181 //     scoped_refptr<MyFoo> foo = MakeRefCounted<MyFoo>();
    182 //     ...
    183 //     foo.reset();  // explicitly releases |foo|
    184 //     ...
    185 //     if (foo)
    186 //       foo->Method(param);
    187 //   }
    188 //
    189 // The above examples show how scoped_refptr<T> acts like a pointer to T.
    190 // Given two scoped_refptr<T> classes, it is also possible to exchange
    191 // references between the two objects, like so:
    192 //
    193 //   {
    194 //     scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>();
    195 //     scoped_refptr<MyFoo> b;
    196 //
    197 //     b.swap(a);
    198 //     // now, |b| references the MyFoo object, and |a| references nullptr.
    199 //   }
    200 //
    201 // To make both |a| and |b| in the above example reference the same MyFoo
    202 // object, simply use the assignment operator:
    203 //
    204 //   {
    205 //     scoped_refptr<MyFoo> a = MakeRefCounted<MyFoo>();
    206 //     scoped_refptr<MyFoo> b;
    207 //
    208 //     b = a;
    209 //     // now, |a| and |b| each own a reference to the same MyFoo object.
    210 //   }
    211 //
    212 // Also see Chromium's ownership and calling conventions:
    213 // https://chromium.googlesource.com/chromium/src/+/lkgr/styleguide/c++/c++.md#object-ownership-and-calling-conventions
    214 // Specifically:
    215 //   If the function (at least sometimes) takes a ref on a refcounted object,
    216 //   declare the param as scoped_refptr<T>. The caller can decide whether it
    217 //   wishes to transfer ownership (by calling std::move(t) when passing t) or
    218 //   retain its ref (by simply passing t directly).
    219 //   In other words, use scoped_refptr like you would a std::unique_ptr except
    220 //   in the odd case where it's required to hold on to a ref while handing one
    221 //   to another component (if a component merely needs to use t on the stack
    222 //   without keeping a ref: pass t as a raw T*).
    223 template <class T>
    224 class TRIVIAL_ABI scoped_refptr {
    225 public:
    226  typedef T element_type;
    227 
    228  constexpr scoped_refptr() = default;
    229 
    230  // Allow implicit construction from nullptr.
    231  constexpr scoped_refptr(std::nullptr_t) {}
    232 
    233  // Constructs from a raw pointer. Note that this constructor allows implicit
    234  // conversion from T* to scoped_refptr<T> which is strongly discouraged. If
    235  // you are creating a new ref-counted object please use
    236  // base::MakeRefCounted<T>() or base::WrapRefCounted<T>(). Otherwise you
    237  // should move or copy construct from an existing scoped_refptr<T> to the
    238  // ref-counted object.
    239  scoped_refptr(T* p) : ptr_(p) {
    240    if (ptr_)
    241      AddRef(ptr_);
    242  }
    243 
    244  // Copy constructor. This is required in addition to the copy conversion
    245  // constructor below.
    246  scoped_refptr(const scoped_refptr& r) : scoped_refptr(r.ptr_) {}
    247 
    248  // Copy conversion constructor.
    249  template <typename U,
    250            typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
    251  scoped_refptr(const scoped_refptr<U>& r) : scoped_refptr(r.ptr_) {}
    252 
    253  // Move constructor. This is required in addition to the move conversion
    254  // constructor below.
    255  scoped_refptr(scoped_refptr&& r) noexcept : ptr_(r.ptr_) { r.ptr_ = nullptr; }
    256 
    257  // Move conversion constructor.
    258  template <typename U,
    259            typename = std::enable_if_t<std::is_convertible_v<U*, T*>>>
    260  scoped_refptr(scoped_refptr<U>&& r) noexcept : ptr_(r.ptr_) {
    261    r.ptr_ = nullptr;
    262  }
    263 
    264  ~scoped_refptr() {
    265    static_assert(!base::subtle::IsRefCountPreferenceOverridden(
    266                      static_cast<T*>(nullptr), static_cast<T*>(nullptr)),
    267                  "It's unsafe to override the ref count preference."
    268                  " Please remove REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE"
    269                  " from subclasses.");
    270    if (ptr_)
    271      Release(ptr_);
    272  }
    273 
    274  T* get() const { return ptr_; }
    275 
    276  T& operator*() const {
    277    DCHECK(ptr_);
    278    return *ptr_;
    279  }
    280 
    281  T* operator->() const {
    282    DCHECK(ptr_);
    283    return ptr_;
    284  }
    285 
    286  scoped_refptr& operator=(std::nullptr_t) {
    287    reset();
    288    return *this;
    289  }
    290 
    291  scoped_refptr& operator=(T* p) { return *this = scoped_refptr(p); }
    292 
    293  // Unified assignment operator.
    294  scoped_refptr& operator=(scoped_refptr r) noexcept {
    295    swap(r);
    296    return *this;
    297  }
    298 
    299  // Sets managed object to null and releases reference to the previous managed
    300  // object, if it existed.
    301  void reset() { scoped_refptr().swap(*this); }
    302 
    303  // Returns the owned pointer (if any), releasing ownership to the caller. The
    304  // caller is responsible for managing the lifetime of the reference.
    305  [[nodiscard]] T* release();
    306 
    307  void swap(scoped_refptr& r) noexcept { std::swap(ptr_, r.ptr_); }
    308 
    309  explicit operator bool() const { return ptr_ != nullptr; }
    310 
    311  template <typename U>
    312  bool operator==(const scoped_refptr<U>& rhs) const {
    313    return ptr_ == rhs.get();
    314  }
    315 
    316  template <typename U>
    317  bool operator!=(const scoped_refptr<U>& rhs) const {
    318    return !operator==(rhs);
    319  }
    320 
    321  template <typename U>
    322  bool operator<(const scoped_refptr<U>& rhs) const {
    323    return ptr_ < rhs.get();
    324  }
    325 
    326 protected:
    327  // This field is not a raw_ptr<> because it was filtered by the rewriter for:
    328  // #union, #addr-of, #global-scope
    329  RAW_PTR_EXCLUSION T* ptr_ = nullptr;
    330 
    331 private:
    332  template <typename U>
    333  friend scoped_refptr<U> base::AdoptRef(U*);
    334  friend class ::base::SequencedTaskRunner;
    335 
    336  scoped_refptr(T* p, base::subtle::AdoptRefTag) : ptr_(p) {}
    337 
    338  // Friend required for move constructors that set r.ptr_ to null.
    339  template <typename U>
    340  friend class scoped_refptr;
    341 
    342  // Non-inline helpers to allow:
    343  //     class Opaque;
    344  //     extern template class scoped_refptr<Opaque>;
    345  // Otherwise the compiler will complain that Opaque is an incomplete type.
    346  static void AddRef(T* ptr);
    347  static void Release(T* ptr);
    348 };
    349 
    350 template <typename T>
    351 T* scoped_refptr<T>::release() {
    352  T* ptr = ptr_;
    353  ptr_ = nullptr;
    354  return ptr;
    355 }
    356 
    357 // static
    358 template <typename T>
    359 void scoped_refptr<T>::AddRef(T* ptr) {
    360  base::subtle::AssertRefCountBaseMatches(ptr, ptr);
    361  ptr->AddRef();
    362 }
    363 
    364 // static
    365 template <typename T>
    366 void scoped_refptr<T>::Release(T* ptr) {
    367  base::subtle::AssertRefCountBaseMatches(ptr, ptr);
    368  ptr->Release();
    369 }
    370 
    371 template <typename T, typename U>
    372 bool operator==(const scoped_refptr<T>& lhs, const U* rhs) {
    373  return lhs.get() == rhs;
    374 }
    375 
    376 template <typename T, typename U>
    377 bool operator==(const T* lhs, const scoped_refptr<U>& rhs) {
    378  return lhs == rhs.get();
    379 }
    380 
    381 template <typename T>
    382 bool operator==(const scoped_refptr<T>& lhs, std::nullptr_t null) {
    383  return !static_cast<bool>(lhs);
    384 }
    385 
    386 template <typename T>
    387 bool operator==(std::nullptr_t null, const scoped_refptr<T>& rhs) {
    388  return !static_cast<bool>(rhs);
    389 }
    390 
    391 template <typename T, typename U>
    392 bool operator!=(const scoped_refptr<T>& lhs, const U* rhs) {
    393  return !operator==(lhs, rhs);
    394 }
    395 
    396 template <typename T, typename U>
    397 bool operator!=(const T* lhs, const scoped_refptr<U>& rhs) {
    398  return !operator==(lhs, rhs);
    399 }
    400 
    401 template <typename T>
    402 bool operator!=(const scoped_refptr<T>& lhs, std::nullptr_t null) {
    403  return !operator==(lhs, null);
    404 }
    405 
    406 template <typename T>
    407 bool operator!=(std::nullptr_t null, const scoped_refptr<T>& rhs) {
    408  return !operator==(null, rhs);
    409 }
    410 
    411 template <typename T>
    412 std::ostream& operator<<(std::ostream& out, const scoped_refptr<T>& p) {
    413  return out << p.get();
    414 }
    415 
    416 template <typename T>
    417 void swap(scoped_refptr<T>& lhs, scoped_refptr<T>& rhs) noexcept {
    418  lhs.swap(rhs);
    419 }
    420 
    421 #endif  // BASE_MEMORY_SCOPED_REFPTR_H_