• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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