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