diff options
Diffstat (limited to 'grpc/src/core/lib/gprpp/ref_counted.h')
-rw-r--r-- | grpc/src/core/lib/gprpp/ref_counted.h | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/grpc/src/core/lib/gprpp/ref_counted.h b/grpc/src/core/lib/gprpp/ref_counted.h index 64f3f8fc..a8def8c9 100644 --- a/grpc/src/core/lib/gprpp/ref_counted.h +++ b/grpc/src/core/lib/gprpp/ref_counted.h @@ -215,31 +215,45 @@ class NonPolymorphicRefCount { ~NonPolymorphicRefCount() = default; }; +// Behavior of RefCounted<> upon ref count reaching 0. +enum UnrefBehavior { + // Default behavior: Delete the object. + kUnrefDelete, + // Do not delete the object upon unref. This is useful in cases where all + // existing objects must be tracked in a registry but the object's entry in + // the registry cannot be removed from the object's dtor due to + // synchronization issues. In this case, the registry can be cleaned up + // later by identifying entries for which RefIfNonZero() returns null. + kUnrefNoDelete, + // Call the object's dtor but do not delete it. This is useful for cases + // where the object is stored in memory allocated elsewhere (e.g., the call + // arena). + kUnrefCallDtor, +}; + namespace internal { -template <typename T, bool DoDelete> +template <typename T, UnrefBehavior UnrefBehaviorArg> class Delete; template <typename T> -class Delete<T, true> { +class Delete<T, kUnrefDelete> { public: explicit Delete(T* t) { delete t; } }; template <typename T> -class Delete<T, false> { +class Delete<T, kUnrefNoDelete> { + public: + explicit Delete(T* /*t*/) {} +}; +template <typename T> +class Delete<T, kUnrefCallDtor> { public: - explicit Delete(T* t) {} + explicit Delete(T* t) { t->~T(); } }; } // namespace internal // A base class for reference-counted objects. // New objects should be created via new and start with a refcount of 1. -// When the refcount reaches 0, the object will be deleted via delete. -// -// If DeleteUponUnref is false, deletion will not occur when the ref -// count reaches 0. This is useful in cases where all existing objects -// must be tracked in a registry but the object's entry in the registry -// cannot be removed from the object's dtor due to synchronization issues. -// In this case, the registry can be cleaned up later by identifying -// entries for which RefIfNonZero() returns null. +// When the refcount reaches 0, executes the specified UnrefBehavior. // // This will commonly be used by CRTP (curiously-recurring template pattern) // e.g., class MyClass : public RefCounted<MyClass> @@ -264,7 +278,7 @@ class Delete<T, false> { // ch->Unref(); // template <typename Child, typename Impl = PolymorphicRefCount, - bool DeleteUponUnref = true> + UnrefBehavior UnrefBehaviorArg = kUnrefDelete> class RefCounted : public Impl { public: // Note: Depending on the Impl used, this dtor can be implicitly virtual. @@ -287,12 +301,12 @@ class RefCounted : public Impl { // friend of this class. void Unref() { if (GPR_UNLIKELY(refs_.Unref())) { - internal::Delete<Child, DeleteUponUnref>(static_cast<Child*>(this)); + internal::Delete<Child, UnrefBehaviorArg>(static_cast<Child*>(this)); } } void Unref(const DebugLocation& location, const char* reason) { if (GPR_UNLIKELY(refs_.Unref(location, reason))) { - internal::Delete<Child, DeleteUponUnref>(static_cast<Child*>(this)); + internal::Delete<Child, UnrefBehaviorArg>(static_cast<Child*>(this)); } } |