diff options
author | Yash Tibrewal <yashkt@google.com> | 2018-11-21 11:48:41 -0800 |
---|---|---|
committer | Yash Tibrewal <yashkt@google.com> | 2018-11-21 11:48:41 -0800 |
commit | 248e30467146efe8bc6f4f05140ae886d743c72d (patch) | |
tree | 73de256fb95a03f6c56fb7fb8e6e0b45f8f1d402 /src/core/lib | |
parent | d704cfe3d11ae32a833e9b995f87d5e2d15bacef (diff) | |
parent | abbfd89dfc7e140fb1658f671b36e3276bfc37ce (diff) |
Merge branch 'master' into httpplumbing
Diffstat (limited to 'src/core/lib')
-rw-r--r-- | src/core/lib/gprpp/ref_counted.h | 73 | ||||
-rw-r--r-- | src/core/lib/surface/version.cc | 2 |
2 files changed, 58 insertions, 17 deletions
diff --git a/src/core/lib/gprpp/ref_counted.h b/src/core/lib/gprpp/ref_counted.h index 81772f3403..e366445bff 100644 --- a/src/core/lib/gprpp/ref_counted.h +++ b/src/core/lib/gprpp/ref_counted.h @@ -24,6 +24,8 @@ #include <grpc/support/log.h> #include <grpc/support/sync.h> +#include <atomic> +#include <cassert> #include <cinttypes> #include "src/core/lib/debug/trace.h" @@ -42,7 +44,7 @@ class PolymorphicRefCount { protected: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - virtual ~PolymorphicRefCount() {} + virtual ~PolymorphicRefCount() = default; }; // NonPolymorphicRefCount does not enforce polymorphic destruction of @@ -55,7 +57,48 @@ class NonPolymorphicRefCount { protected: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - ~NonPolymorphicRefCount() {} + ~NonPolymorphicRefCount() = default; +}; + +// RefCount is a simple atomic ref-count. +// +// This is a C++ implementation of gpr_refcount, with inline functions. Due to +// inline functions, this class is significantly more efficient than +// gpr_refcount and should be preferred over gpr_refcount whenever possible. +// +// TODO(soheil): Remove gpr_refcount after submitting the GRFC and the paragraph +// above. +class RefCount { + public: + using Value = intptr_t; + + // `init` is the initial refcount stored in this object. + constexpr explicit RefCount(Value init = 1) : value_(init) {} + + // Increases the ref-count by `n`. + void Ref(Value n = 1) { value_.fetch_add(n, std::memory_order_relaxed); } + + // Similar to Ref() with an assert on the ref-count being non-zero. + void RefNonZero() { +#ifndef NDEBUG + const Value prior = value_.fetch_add(1, std::memory_order_relaxed); + assert(prior > 0); +#else + Ref(); +#endif + } + + // Decrements the ref-count and returns true if the ref-count reaches 0. + bool Unref() { + const Value prior = value_.fetch_sub(1, std::memory_order_acq_rel); + GPR_DEBUG_ASSERT(prior > 0); + return prior == 1; + } + + Value get() const { return value_.load(std::memory_order_relaxed); } + + private: + std::atomic<Value> value_; }; // A base class for reference-counted objects. @@ -97,7 +140,7 @@ class RefCounted : public Impl { // private, since it will only be used by RefCountedPtr<>, which is a // friend of this class. void Unref() { - if (gpr_unref(&refs_)) { + if (refs_.Unref()) { Delete(static_cast<Child*>(this)); } } @@ -111,19 +154,19 @@ class RefCounted : public Impl { protected: GPRC_ALLOW_CLASS_TO_USE_NON_PUBLIC_DELETE - RefCounted() { gpr_ref_init(&refs_, 1); } + RefCounted() = default; // Note: Depending on the Impl used, this dtor can be implicitly virtual. - ~RefCounted() {} + ~RefCounted() = default; private: // Allow RefCountedPtr<> to access IncrementRefCount(). template <typename T> friend class RefCountedPtr; - void IncrementRefCount() { gpr_ref(&refs_); } + void IncrementRefCount() { refs_.Ref(); } - gpr_refcount refs_; + RefCount refs_; }; // An alternative version of the RefCounted base class that @@ -143,7 +186,7 @@ class RefCountedWithTracing : public Impl { RefCountedPtr<Child> Ref(const DebugLocation& location, const char* reason) GRPC_MUST_USE_RESULT { if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { - gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); + const RefCount::Value old_refs = refs_.get(); gpr_log(GPR_INFO, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s", trace_flag_->name(), this, location.file(), location.line(), old_refs, old_refs + 1, reason); @@ -157,14 +200,14 @@ class RefCountedWithTracing : public Impl { // friend of this class. void Unref() { - if (gpr_unref(&refs_)) { + if (refs_.Unref()) { Delete(static_cast<Child*>(this)); } } void Unref(const DebugLocation& location, const char* reason) { if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) { - gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count); + const RefCount::Value old_refs = refs_.get(); gpr_log(GPR_INFO, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s", trace_flag_->name(), this, location.file(), location.line(), old_refs, old_refs - 1, reason); @@ -185,9 +228,7 @@ class RefCountedWithTracing : public Impl { : RefCountedWithTracing(static_cast<TraceFlag*>(nullptr)) {} explicit RefCountedWithTracing(TraceFlag* trace_flag) - : trace_flag_(trace_flag) { - gpr_ref_init(&refs_, 1); - } + : trace_flag_(trace_flag) {} #ifdef NDEBUG explicit RefCountedWithTracing(DebugOnlyTraceFlag* trace_flag) @@ -195,17 +236,17 @@ class RefCountedWithTracing : public Impl { #endif // Note: Depending on the Impl used, this dtor can be implicitly virtual. - ~RefCountedWithTracing() {} + ~RefCountedWithTracing() = default; private: // Allow RefCountedPtr<> to access IncrementRefCount(). template <typename T> friend class RefCountedPtr; - void IncrementRefCount() { gpr_ref(&refs_); } + void IncrementRefCount() { refs_.Ref(); } TraceFlag* trace_flag_ = nullptr; - gpr_refcount refs_; + RefCount refs_; }; } // namespace grpc_core diff --git a/src/core/lib/surface/version.cc b/src/core/lib/surface/version.cc index 66890ce65a..4829cc80a5 100644 --- a/src/core/lib/surface/version.cc +++ b/src/core/lib/surface/version.cc @@ -25,4 +25,4 @@ const char* grpc_version_string(void) { return "7.0.0-dev"; } -const char* grpc_g_stands_for(void) { return "gizmo"; } +const char* grpc_g_stands_for(void) { return "goose"; } |