summaryrefslogtreecommitdiff
path: root/grpc/src/core/lib/gprpp/ref_counted.h
diff options
context:
space:
mode:
Diffstat (limited to 'grpc/src/core/lib/gprpp/ref_counted.h')
-rw-r--r--grpc/src/core/lib/gprpp/ref_counted.h44
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));
}
}