|  | // Copyright (c) 2016 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_REFERENCE_COUNTED_H_ | 
|  | #define QUICHE_COMMON_PLATFORM_API_QUICHE_REFERENCE_COUNTED_H_ | 
|  |  | 
|  | #include "quiche_platform_impl/quiche_reference_counted_impl.h" | 
|  | #include "quiche/common/platform/api/quiche_export.h" | 
|  |  | 
|  | namespace quiche { | 
|  |  | 
|  | // Base class for explicitly reference-counted objects in QUIC. | 
|  | class QUICHE_EXPORT QuicheReferenceCounted : public QuicheReferenceCountedImpl { | 
|  | public: | 
|  | QuicheReferenceCounted() {} | 
|  |  | 
|  | protected: | 
|  | ~QuicheReferenceCounted() override {} | 
|  | }; | 
|  |  | 
|  | // A class representing a reference counted pointer in QUIC. | 
|  | // | 
|  | // Construct or initialize QuicheReferenceCountedPointer from raw pointer. Here | 
|  | // raw pointer MUST be a newly created object. Reference count of a newly | 
|  | // created object is undefined, but that will be 1 after being added to | 
|  | // QuicheReferenceCountedPointer. | 
|  | // QuicheReferenceCountedPointer is used as a local variable. | 
|  | // QuicheReferenceCountedPointer<T> r_ptr(new T()); | 
|  | // or, equivalently: | 
|  | // QuicheReferenceCountedPointer<T> r_ptr; | 
|  | // T* p = new T(); | 
|  | // r_ptr = T; | 
|  | // | 
|  | // QuicheReferenceCountedPointer is used as a member variable: | 
|  | // MyClass::MyClass() : r_ptr(new T()) {} | 
|  | // | 
|  | // This is WRONG, since *p is not guaranteed to be newly created: | 
|  | // MyClass::MyClass(T* p) : r_ptr(p) {} | 
|  | // | 
|  | // Given an existing QuicheReferenceCountedPointer, create a duplicate that has | 
|  | // its own reference on the object: | 
|  | // QuicheReferenceCountedPointer<T> r_ptr_b(r_ptr_a); | 
|  | // or, equivalently: | 
|  | // QuicheReferenceCountedPointer<T> r_ptr_b = r_ptr_a; | 
|  | // | 
|  | // Given an existing QuicheReferenceCountedPointer, create a | 
|  | // QuicheReferenceCountedPointer that adopts the reference: | 
|  | // QuicheReferenceCountedPointer<T> r_ptr_b(std::move(r_ptr_a)); | 
|  | // or, equivalently: | 
|  | // QuicheReferenceCountedPointer<T> r_ptr_b = std::move(r_ptr_a); | 
|  |  | 
|  | template <class T> | 
|  | class QUICHE_NO_EXPORT QuicheReferenceCountedPointer { | 
|  | public: | 
|  | QuicheReferenceCountedPointer() = default; | 
|  |  | 
|  | // Constructor from raw pointer |p|. This guarantees that the reference count | 
|  | // of *p is 1. This should be only called when a new object is created. | 
|  | // Calling this on an already existent object does not increase its reference | 
|  | // count. | 
|  | explicit QuicheReferenceCountedPointer(T* p) : impl_(p) {} | 
|  |  | 
|  | // Allows implicit conversion from nullptr. | 
|  | QuicheReferenceCountedPointer(std::nullptr_t) : impl_(nullptr) {}  // NOLINT | 
|  |  | 
|  | // Copy and copy conversion constructors. It does not take the reference away | 
|  | // from |other| and they each end up with their own reference. | 
|  | template <typename U> | 
|  | QuicheReferenceCountedPointer(  // NOLINT | 
|  | const QuicheReferenceCountedPointer<U>& other) | 
|  | : impl_(other.impl()) {} | 
|  | QuicheReferenceCountedPointer(const QuicheReferenceCountedPointer& other) | 
|  | : impl_(other.impl()) {} | 
|  |  | 
|  | // Move constructors. After move, it adopts the reference from |other|. | 
|  | template <typename U> | 
|  | QuicheReferenceCountedPointer( | 
|  | QuicheReferenceCountedPointer<U>&& other)  // NOLINT | 
|  | : impl_(std::move(other.impl())) {} | 
|  | QuicheReferenceCountedPointer(QuicheReferenceCountedPointer&& other) | 
|  | : impl_(std::move(other.impl())) {} | 
|  |  | 
|  | ~QuicheReferenceCountedPointer() = default; | 
|  |  | 
|  | // Copy assignments. | 
|  | QuicheReferenceCountedPointer& operator=( | 
|  | const QuicheReferenceCountedPointer& other) { | 
|  | impl_ = other.impl(); | 
|  | return *this; | 
|  | } | 
|  | template <typename U> | 
|  | QuicheReferenceCountedPointer<T>& operator=( | 
|  | const QuicheReferenceCountedPointer<U>& other) { | 
|  | impl_ = other.impl(); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | // Move assignments. | 
|  | QuicheReferenceCountedPointer& operator=( | 
|  | QuicheReferenceCountedPointer&& other) { | 
|  | impl_ = std::move(other.impl()); | 
|  | return *this; | 
|  | } | 
|  | template <typename U> | 
|  | QuicheReferenceCountedPointer<T>& operator=( | 
|  | QuicheReferenceCountedPointer<U>&& other) { | 
|  | impl_ = std::move(other.impl()); | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | // Accessors for the referenced object. | 
|  | // operator*() and operator->() will assert() if there is no current object. | 
|  | T& operator*() const { return *impl_; } | 
|  | T* operator->() const { return impl_.get(); } | 
|  |  | 
|  | explicit operator bool() const { return static_cast<bool>(impl_); } | 
|  |  | 
|  | // Assignment operator on raw pointer. Drops a reference to current pointee, | 
|  | // if any, and replaces it with |p|. This guarantees that the reference count | 
|  | // of *p is 1. This should only be used when a new object is created.  Calling | 
|  | // this on an already existent object is undefined behavior. | 
|  | QuicheReferenceCountedPointer<T>& operator=(T* p) { | 
|  | impl_ = p; | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | // Returns the raw pointer with no change in reference count. | 
|  | T* get() const { return impl_.get(); } | 
|  |  | 
|  | QuicheReferenceCountedPointerImpl<T>& impl() { return impl_; } | 
|  | const QuicheReferenceCountedPointerImpl<T>& impl() const { return impl_; } | 
|  |  | 
|  | // Comparisons against same type. | 
|  | friend bool operator==(const QuicheReferenceCountedPointer& a, | 
|  | const QuicheReferenceCountedPointer& b) { | 
|  | return a.get() == b.get(); | 
|  | } | 
|  | friend bool operator!=(const QuicheReferenceCountedPointer& a, | 
|  | const QuicheReferenceCountedPointer& b) { | 
|  | return a.get() != b.get(); | 
|  | } | 
|  |  | 
|  | // Comparisons against nullptr. | 
|  | friend bool operator==(const QuicheReferenceCountedPointer& a, | 
|  | std::nullptr_t) { | 
|  | return a.get() == nullptr; | 
|  | } | 
|  | friend bool operator==(std::nullptr_t, | 
|  | const QuicheReferenceCountedPointer& b) { | 
|  | return nullptr == b.get(); | 
|  | } | 
|  | friend bool operator!=(const QuicheReferenceCountedPointer& a, | 
|  | std::nullptr_t) { | 
|  | return a.get() != nullptr; | 
|  | } | 
|  | friend bool operator!=(std::nullptr_t, | 
|  | const QuicheReferenceCountedPointer& b) { | 
|  | return nullptr != b.get(); | 
|  | } | 
|  |  | 
|  | private: | 
|  | QuicheReferenceCountedPointerImpl<T> impl_; | 
|  | }; | 
|  |  | 
|  | }  // namespace quiche | 
|  |  | 
|  | #endif  // QUICHE_COMMON_PLATFORM_API_QUICHE_REFERENCE_COUNTED_H_ |