1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. 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 QUICHE_COMMON_PLATFORM_API_QUICHE_REFERENCE_COUNTED_H_ 6 #define QUICHE_COMMON_PLATFORM_API_QUICHE_REFERENCE_COUNTED_H_ 7 8 #include "quiche_platform_impl/quiche_reference_counted_impl.h" 9 10 #include "quiche/common/platform/api/quiche_export.h" 11 12 namespace quiche { 13 14 // Base class for explicitly reference-counted objects in QUIC. 15 class QUICHE_EXPORT QuicheReferenceCounted : public QuicheReferenceCountedImpl { 16 public: QuicheReferenceCounted()17 QuicheReferenceCounted() {} 18 19 protected: ~QuicheReferenceCounted()20 ~QuicheReferenceCounted() override {} 21 }; 22 23 // A class representing a reference counted pointer in QUIC. 24 // 25 // Construct or initialize QuicheReferenceCountedPointer from raw pointer. Here 26 // raw pointer MUST be a newly created object. Reference count of a newly 27 // created object is undefined, but that will be 1 after being added to 28 // QuicheReferenceCountedPointer. 29 // QuicheReferenceCountedPointer is used as a local variable. 30 // QuicheReferenceCountedPointer<T> r_ptr(new T()); 31 // or, equivalently: 32 // QuicheReferenceCountedPointer<T> r_ptr; 33 // T* p = new T(); 34 // r_ptr = T; 35 // 36 // QuicheReferenceCountedPointer is used as a member variable: 37 // MyClass::MyClass() : r_ptr(new T()) {} 38 // 39 // This is WRONG, since *p is not guaranteed to be newly created: 40 // MyClass::MyClass(T* p) : r_ptr(p) {} 41 // 42 // Given an existing QuicheReferenceCountedPointer, create a duplicate that has 43 // its own reference on the object: 44 // QuicheReferenceCountedPointer<T> r_ptr_b(r_ptr_a); 45 // or, equivalently: 46 // QuicheReferenceCountedPointer<T> r_ptr_b = r_ptr_a; 47 // 48 // Given an existing QuicheReferenceCountedPointer, create a 49 // QuicheReferenceCountedPointer that adopts the reference: 50 // QuicheReferenceCountedPointer<T> r_ptr_b(std::move(r_ptr_a)); 51 // or, equivalently: 52 // QuicheReferenceCountedPointer<T> r_ptr_b = std::move(r_ptr_a); 53 54 template <class T> 55 class QUICHE_NO_EXPORT QuicheReferenceCountedPointer { 56 public: 57 QuicheReferenceCountedPointer() = default; 58 59 // Constructor from raw pointer |p|. This guarantees that the reference count 60 // of *p is 1. This should be only called when a new object is created. 61 // Calling this on an already existent object does not increase its reference 62 // count. QuicheReferenceCountedPointer(T * p)63 explicit QuicheReferenceCountedPointer(T* p) : impl_(p) {} 64 65 // Allows implicit conversion from nullptr. QuicheReferenceCountedPointer(std::nullptr_t)66 QuicheReferenceCountedPointer(std::nullptr_t) : impl_(nullptr) {} // NOLINT 67 68 // Copy and copy conversion constructors. It does not take the reference away 69 // from |other| and they each end up with their own reference. 70 template <typename U> QuicheReferenceCountedPointer(const QuicheReferenceCountedPointer<U> & other)71 QuicheReferenceCountedPointer( // NOLINT 72 const QuicheReferenceCountedPointer<U>& other) 73 : impl_(other.impl()) {} QuicheReferenceCountedPointer(const QuicheReferenceCountedPointer & other)74 QuicheReferenceCountedPointer(const QuicheReferenceCountedPointer& other) 75 : impl_(other.impl()) {} 76 77 // Move constructors. After move, it adopts the reference from |other|. 78 template <typename U> QuicheReferenceCountedPointer(QuicheReferenceCountedPointer<U> && other)79 QuicheReferenceCountedPointer( 80 QuicheReferenceCountedPointer<U>&& other) // NOLINT 81 : impl_(std::move(other.impl())) {} QuicheReferenceCountedPointer(QuicheReferenceCountedPointer && other)82 QuicheReferenceCountedPointer(QuicheReferenceCountedPointer&& other) 83 : impl_(std::move(other.impl())) {} 84 85 ~QuicheReferenceCountedPointer() = default; 86 87 // Copy assignments. 88 QuicheReferenceCountedPointer& operator=( 89 const QuicheReferenceCountedPointer& other) { 90 impl_ = other.impl(); 91 return *this; 92 } 93 template <typename U> 94 QuicheReferenceCountedPointer<T>& operator=( 95 const QuicheReferenceCountedPointer<U>& other) { 96 impl_ = other.impl(); 97 return *this; 98 } 99 100 // Move assignments. 101 QuicheReferenceCountedPointer& operator=( 102 QuicheReferenceCountedPointer&& other) { 103 impl_ = std::move(other.impl()); 104 return *this; 105 } 106 template <typename U> 107 QuicheReferenceCountedPointer<T>& operator=( 108 QuicheReferenceCountedPointer<U>&& other) { 109 impl_ = std::move(other.impl()); 110 return *this; 111 } 112 113 // Accessors for the referenced object. 114 // operator*() and operator->() will assert() if there is no current object. 115 T& operator*() const { return *impl_; } 116 T* operator->() const { return impl_.get(); } 117 118 explicit operator bool() const { return static_cast<bool>(impl_); } 119 120 // Assignment operator on raw pointer. Drops a reference to current pointee, 121 // if any, and replaces it with |p|. This guarantees that the reference count 122 // of *p is 1. This should only be used when a new object is created. Calling 123 // this on an already existent object is undefined behavior. 124 QuicheReferenceCountedPointer<T>& operator=(T* p) { 125 impl_ = p; 126 return *this; 127 } 128 129 // Returns the raw pointer with no change in reference count. get()130 T* get() const { return impl_.get(); } 131 impl()132 QuicheReferenceCountedPointerImpl<T>& impl() { return impl_; } impl()133 const QuicheReferenceCountedPointerImpl<T>& impl() const { return impl_; } 134 135 // Comparisons against same type. 136 friend bool operator==(const QuicheReferenceCountedPointer& a, 137 const QuicheReferenceCountedPointer& b) { 138 return a.get() == b.get(); 139 } 140 friend bool operator!=(const QuicheReferenceCountedPointer& a, 141 const QuicheReferenceCountedPointer& b) { 142 return a.get() != b.get(); 143 } 144 145 // Comparisons against nullptr. 146 friend bool operator==(const QuicheReferenceCountedPointer& a, 147 std::nullptr_t) { 148 return a.get() == nullptr; 149 } 150 friend bool operator==(std::nullptr_t, 151 const QuicheReferenceCountedPointer& b) { 152 return nullptr == b.get(); 153 } 154 friend bool operator!=(const QuicheReferenceCountedPointer& a, 155 std::nullptr_t) { 156 return a.get() != nullptr; 157 } 158 friend bool operator!=(std::nullptr_t, 159 const QuicheReferenceCountedPointer& b) { 160 return nullptr != b.get(); 161 } 162 163 private: 164 QuicheReferenceCountedPointerImpl<T> impl_; 165 }; 166 167 } // namespace quiche 168 169 #endif // QUICHE_COMMON_PLATFORM_API_QUICHE_REFERENCE_COUNTED_H_ 170