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