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_