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_