diff options
Diffstat (limited to 'src/core/lib/gprpp/orphanable.h')
-rw-r--r-- | src/core/lib/gprpp/orphanable.h | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/src/core/lib/gprpp/orphanable.h b/src/core/lib/gprpp/orphanable.h index 50199730c9..78d1b01ff8 100644 --- a/src/core/lib/gprpp/orphanable.h +++ b/src/core/lib/gprpp/orphanable.h @@ -28,6 +28,7 @@ #include "src/core/lib/gprpp/abstract.h" #include "src/core/lib/gprpp/debug_location.h" #include "src/core/lib/gprpp/memory.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" namespace grpc_core { @@ -69,6 +70,7 @@ inline OrphanablePtr<T> MakeOrphanable(Args&&... args) { } // A type of Orphanable with internal ref-counting. +template <typename Child> class InternallyRefCounted : public Orphanable { public: // Not copyable nor movable. @@ -78,10 +80,20 @@ class InternallyRefCounted : public Orphanable { GRPC_ABSTRACT_BASE_CLASS protected: + // Allow Delete() to access destructor. + template <typename T> + friend void Delete(T*); + + // Allow RefCountedPtr<> to access Unref() and IncrementRefCount(). + friend class RefCountedPtr<Child>; + InternallyRefCounted() { gpr_ref_init(&refs_, 1); } virtual ~InternallyRefCounted() {} - void Ref() { gpr_ref(&refs_); } + RefCountedPtr<Child> Ref() GRPC_MUST_USE_RESULT { + IncrementRefCount(); + return RefCountedPtr<Child>(static_cast<Child*>(this)); + } void Unref() { if (gpr_unref(&refs_)) { @@ -89,11 +101,9 @@ class InternallyRefCounted : public Orphanable { } } - // Allow Delete() to access destructor. - template <typename T> - friend void Delete(T*); - private: + void IncrementRefCount() { gpr_ref(&refs_); } + gpr_refcount refs_; }; @@ -103,6 +113,7 @@ class InternallyRefCounted : public Orphanable { // pointers and legacy code that is manually calling Ref() and Unref(). // Once all of our code is converted to idiomatic C++, we may be able to // eliminate this class. +template <typename Child> class InternallyRefCountedWithTracing : public Orphanable { public: // Not copyable nor movable. @@ -118,6 +129,9 @@ class InternallyRefCountedWithTracing : public Orphanable { template <typename T> friend void Delete(T*); + // Allow RefCountedPtr<> to access Unref() and IncrementRefCount(). + friend class RefCountedPtr<Child>; + InternallyRefCountedWithTracing() : InternallyRefCountedWithTracing(static_cast<TraceFlag*>(nullptr)) {} @@ -133,18 +147,27 @@ class InternallyRefCountedWithTracing : public Orphanable { virtual ~InternallyRefCountedWithTracing() {} - void Ref() { gpr_ref(&refs_); } + RefCountedPtr<Child> Ref() GRPC_MUST_USE_RESULT { + IncrementRefCount(); + return RefCountedPtr<Child>(static_cast<Child*>(this)); + } - void Ref(const DebugLocation& location, const char* reason) { + 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); gpr_log(GPR_DEBUG, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s", trace_flag_->name(), this, location.file(), location.line(), old_refs, old_refs + 1, reason); } - Ref(); + return Ref(); } + // TODO(roth): Once all of our code is converted to C++ and can use + // RefCountedPtr<> instead of manual ref-counting, make the Unref() methods + // private, since they will only be used by RefCountedPtr<>, which is a + // friend of this class. + void Unref() { if (gpr_unref(&refs_)) { Delete(this); @@ -162,6 +185,8 @@ class InternallyRefCountedWithTracing : public Orphanable { } private: + void IncrementRefCount() { gpr_ref(&refs_); } + TraceFlag* trace_flag_ = nullptr; gpr_refcount refs_; }; |