xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/common/platform/api/quiche_reference_counted.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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