Provide default implementation of QuicheReferenceCounted. PiperOrigin-RevId: 433309089
diff --git a/common/platform/api/quiche_reference_counted.h b/common/platform/api/quiche_reference_counted.h index 82fce6d..6585a30 100644 --- a/common/platform/api/quiche_reference_counted.h +++ b/common/platform/api/quiche_reference_counted.h
@@ -5,8 +5,8 @@ #ifndef QUICHE_QUIC_PLATFORM_API_QUIC_REFERENCE_COUNTED_H_ #define QUICHE_QUIC_PLATFORM_API_QUIC_REFERENCE_COUNTED_H_ +#include "quiche_platform_impl/quiche_reference_counted_impl.h" #include "common/platform/api/quiche_export.h" -#include "net/quiche/common/platform/impl/quiche_reference_counted_impl.h" namespace quiche {
diff --git a/common/platform/api/quiche_reference_counted_test.cc b/common/platform/api/quiche_reference_counted_test.cc index bb4dc4f..5248e4e 100644 --- a/common/platform/api/quiche_reference_counted_test.cc +++ b/common/platform/api/quiche_reference_counted_test.cc
@@ -4,7 +4,7 @@ #include "common/platform/api/quiche_reference_counted.h" -#include "quic/platform/api/quic_test.h" +#include "common/platform/api/quiche_test.h" namespace quiche { namespace test { @@ -31,7 +31,7 @@ ~Derived() override {} }; -class QuicheReferenceCountedTest : public QuicTest {}; +class QuicheReferenceCountedTest : public QuicheTest {}; TEST_F(QuicheReferenceCountedTest, DefaultConstructor) { QuicheReferenceCountedPointer<Base> a;
diff --git a/common/platform/default/quiche_platform_impl/quiche_reference_counted_impl.h b/common/platform/default/quiche_platform_impl/quiche_reference_counted_impl.h new file mode 100644 index 0000000..1447b54 --- /dev/null +++ b/common/platform/default/quiche_platform_impl/quiche_reference_counted_impl.h
@@ -0,0 +1,190 @@ +// Copyright (c) 2022 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_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_REFERENCE_COUNTED_IMPL_H_ +#define QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_REFERENCE_COUNTED_IMPL_H_ + +#include <atomic> +#include <memory> + +#include "absl/base/attributes.h" +#include "common/platform/api/quiche_export.h" +#include "common/platform/api/quiche_logging.h" + +namespace quiche { + +class QUICHE_EXPORT_PRIVATE QuicheReferenceCountedImpl { + public: + virtual ~QuicheReferenceCountedImpl() { QUICHE_DCHECK_EQ(ref_count_, 0); } + + void AddReference() { ref_count_.fetch_add(1, std::memory_order_relaxed); } + + // Returns true if the objects needs to be deleted. + ABSL_MUST_USE_RESULT bool RemoveReference() { + int new_count = ref_count_.fetch_sub(1, std::memory_order_acq_rel) - 1; + QUICHE_DCHECK_GE(new_count, 0); + return new_count == 0; + } + + bool HasUniqueReference() const { + return ref_count_.load(std::memory_order_acquire) == 1; + } + + private: + std::atomic<int> ref_count_ = 1; +}; + +template <class T> +class QUICHE_NO_EXPORT QuicheReferenceCountedPointerImpl { + public: + QuicheReferenceCountedPointerImpl() = default; + ~QuicheReferenceCountedPointerImpl() { RemoveReference(); } + + // 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. + explicit QuicheReferenceCountedPointerImpl(T* p) : object_(p) { + if (p != nullptr) { + QUICHE_DCHECK(p->HasUniqueReference()); + } + } + + explicit QuicheReferenceCountedPointerImpl(std::nullptr_t) + : object_(nullptr) {} + + // Copy and copy conversion constructors. + QuicheReferenceCountedPointerImpl( + const QuicheReferenceCountedPointerImpl& other) { + AssignObject(other.get()); + AddReference(); + } + template <typename U> + QuicheReferenceCountedPointerImpl( // NOLINT + const QuicheReferenceCountedPointerImpl<U>& other) { + AssignObject(other.get()); + AddReference(); + } + + // Move constructors. + QuicheReferenceCountedPointerImpl(QuicheReferenceCountedPointerImpl&& other) { + object_ = other.object_; + other.object_ = nullptr; + } + template <typename U> + QuicheReferenceCountedPointerImpl( + QuicheReferenceCountedPointerImpl<U>&& other) { // NOLINT + // We can't access other.object_ since other has different T and object_ is + // private. + object_ = other.get(); + AddReference(); + other = nullptr; + } + + // Copy assignments. + QuicheReferenceCountedPointerImpl& operator=( + const QuicheReferenceCountedPointerImpl& other) { + AssignObject(other.object_); + AddReference(); + return *this; + } + template <typename U> + QuicheReferenceCountedPointerImpl<T>& operator=( + const QuicheReferenceCountedPointerImpl<U>& other) { + AssignObject(other.object_); + AddReference(); + return *this; + } + + // Move assignments. + QuicheReferenceCountedPointerImpl& operator=( + QuicheReferenceCountedPointerImpl&& other) { + AssignObject(other.object_); + other.object_ = nullptr; + return *this; + } + template <typename U> + QuicheReferenceCountedPointerImpl<T>& operator=( + QuicheReferenceCountedPointerImpl<U>&& other) { + AssignObject(other.get()); + AddReference(); + other = nullptr; + return *this; + } + + T& operator*() const { return *object_; } + T* operator->() const { return object_; } + + explicit operator bool() const { return object_ != nullptr; } + + // Assignment operator on raw pointer. Behaves similar to the raw pointer + // constructor. + QuicheReferenceCountedPointerImpl<T>& operator=(T* p) { + AssignObject(p); + if (p != nullptr) { + QUICHE_DCHECK(p->HasUniqueReference()); + } + return *this; + } + + // Returns the raw pointer with no change in reference count. + T* get() const { return object_; } + + // Comparisons against same type. + friend bool operator==(const QuicheReferenceCountedPointerImpl& a, + const QuicheReferenceCountedPointerImpl& b) { + return a.get() == b.get(); + } + friend bool operator!=(const QuicheReferenceCountedPointerImpl& a, + const QuicheReferenceCountedPointerImpl& b) { + return a.get() != b.get(); + } + + // Comparisons against nullptr. + friend bool operator==(const QuicheReferenceCountedPointerImpl& a, + std::nullptr_t) { + return a.get() == nullptr; + } + friend bool operator==(std::nullptr_t, + const QuicheReferenceCountedPointerImpl& b) { + return nullptr == b.get(); + } + friend bool operator!=(const QuicheReferenceCountedPointerImpl& a, + std::nullptr_t) { + return a.get() != nullptr; + } + friend bool operator!=(std::nullptr_t, + const QuicheReferenceCountedPointerImpl& b) { + return nullptr != b.get(); + } + + private: + void AddReference() { + if (object_ == nullptr) { + return; + } + QuicheReferenceCountedImpl* implicitly_cast_object = object_; + implicitly_cast_object->AddReference(); + } + + void RemoveReference() { + if (object_ == nullptr) { + return; + } + QuicheReferenceCountedImpl* implicitly_cast_object = object_; + if (implicitly_cast_object->RemoveReference()) { + delete implicitly_cast_object; + } + object_ = nullptr; + } + + void AssignObject(T* new_object) { + RemoveReference(); + object_ = new_object; + } + + T* object_ = nullptr; +}; + +} // namespace quiche + +#endif // QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_REFERENCE_COUNTED_IMPL_H_