diff options
Diffstat (limited to 'src/core/lib/gprpp/ref_counted.h')
-rw-r--r-- | src/core/lib/gprpp/ref_counted.h | 85 |
1 files changed, 63 insertions, 22 deletions
diff --git a/src/core/lib/gprpp/ref_counted.h b/src/core/lib/gprpp/ref_counted.h index cdf692c5ce..9d56397fdb 100644 --- a/src/core/lib/gprpp/ref_counted.h +++ b/src/core/lib/gprpp/ref_counted.h @@ -219,7 +219,7 @@ class NonPolymorphicRefCount { // Default behavior: Delete the object. struct UnrefDelete { template <typename T> - void operator()(T* p) { + void operator()(T* p) const { delete p; } }; @@ -231,7 +231,7 @@ struct UnrefDelete { // later by identifying entries for which RefIfNonZero() returns null. struct UnrefNoDelete { template <typename T> - void operator()(T* /*p*/) {} + void operator()(T* /*p*/) const {} }; // Call the object's dtor but do not delete it. This is useful for cases @@ -239,7 +239,7 @@ struct UnrefNoDelete { // arena). struct UnrefCallDtor { template <typename T> - void operator()(T* p) { + void operator()(T* p) const { p->~T(); } }; @@ -276,35 +276,52 @@ class RefCounted : public Impl { public: using RefCountedChildType = Child; + // Not copyable nor movable. + RefCounted(const RefCounted&) = delete; + RefCounted& operator=(const RefCounted&) = delete; + // Note: Depending on the Impl used, this dtor can be implicitly virtual. ~RefCounted() = default; + // Ref() for mutable types. GRPC_MUST_USE_RESULT RefCountedPtr<Child> Ref() { IncrementRefCount(); return RefCountedPtr<Child>(static_cast<Child*>(this)); } - GRPC_MUST_USE_RESULT RefCountedPtr<Child> Ref(const DebugLocation& location, const char* reason) { IncrementRefCount(location, reason); return RefCountedPtr<Child>(static_cast<Child*>(this)); } - // TODO(roth): Once all of our code is converted to C++ and can use - // RefCountedPtr<> instead of manual ref-counting, make this method - // private, since it will only be used by RefCountedPtr<>, which is a - // friend of this class. - void Unref() { - if (GPR_UNLIKELY(refs_.Unref())) { - unref_behavior_(static_cast<Child*>(this)); - } + // Ref() for const types. + GRPC_MUST_USE_RESULT RefCountedPtr<const Child> Ref() const { + IncrementRefCount(); + return RefCountedPtr<const Child>(static_cast<const Child*>(this)); } - void Unref(const DebugLocation& location, const char* reason) { - if (GPR_UNLIKELY(refs_.Unref(location, reason))) { - unref_behavior_(static_cast<Child*>(this)); - } + GRPC_MUST_USE_RESULT RefCountedPtr<const Child> Ref( + const DebugLocation& location, const char* reason) const { + IncrementRefCount(location, reason); + return RefCountedPtr<const Child>(static_cast<const Child*>(this)); + } + + template < + typename Subclass, + std::enable_if_t<std::is_base_of<Child, Subclass>::value, bool> = true> + RefCountedPtr<Subclass> RefAsSubclass() { + IncrementRefCount(); + return RefCountedPtr<Subclass>(static_cast<Subclass*>(this)); + } + template < + typename Subclass, + std::enable_if_t<std::is_base_of<Child, Subclass>::value, bool> = true> + RefCountedPtr<Subclass> RefAsSubclass(const DebugLocation& location, + const char* reason) { + IncrementRefCount(location, reason); + return RefCountedPtr<Subclass>(static_cast<Subclass*>(this)); } + // RefIfNonZero() for mutable types. GRPC_MUST_USE_RESULT RefCountedPtr<Child> RefIfNonZero() { return RefCountedPtr<Child>(refs_.RefIfNonZero() ? static_cast<Child*>(this) : nullptr); @@ -316,9 +333,32 @@ class RefCounted : public Impl { : nullptr); } - // Not copyable nor movable. - RefCounted(const RefCounted&) = delete; - RefCounted& operator=(const RefCounted&) = delete; + // RefIfNonZero() for const types. + GRPC_MUST_USE_RESULT RefCountedPtr<const Child> RefIfNonZero() const { + return RefCountedPtr<const Child>( + refs_.RefIfNonZero() ? static_cast<const Child*>(this) : nullptr); + } + GRPC_MUST_USE_RESULT RefCountedPtr<const Child> RefIfNonZero( + const DebugLocation& location, const char* reason) const { + return RefCountedPtr<const Child>(refs_.RefIfNonZero(location, reason) + ? static_cast<const Child*>(this) + : nullptr); + } + + // TODO(roth): Once all of our code is converted to C++ and can use + // RefCountedPtr<> instead of manual ref-counting, make this method + // private, since it will only be used by RefCountedPtr<>, which is a + // friend of this class. + void Unref() const { + if (GPR_UNLIKELY(refs_.Unref())) { + unref_behavior_(static_cast<const Child*>(this)); + } + } + void Unref(const DebugLocation& location, const char* reason) const { + if (GPR_UNLIKELY(refs_.Unref(location, reason))) { + unref_behavior_(static_cast<const Child*>(this)); + } + } protected: // Note: Tracing is a no-op on non-debug builds. @@ -336,12 +376,13 @@ class RefCounted : public Impl { template <typename T> friend class RefCountedPtr; - void IncrementRefCount() { refs_.Ref(); } - void IncrementRefCount(const DebugLocation& location, const char* reason) { + void IncrementRefCount() const { refs_.Ref(); } + void IncrementRefCount(const DebugLocation& location, + const char* reason) const { refs_.Ref(location, reason); } - RefCount refs_; + mutable RefCount refs_; GPR_NO_UNIQUE_ADDRESS UnrefBehavior unref_behavior_; }; |