3 * Copyright 2017 gRPC authors.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #ifndef GRPC_CORE_LIB_GPRPP_REF_COUNTED_PTR_H
20 #define GRPC_CORE_LIB_GPRPP_REF_COUNTED_PTR_H
22 #include <grpc/support/port_platform.h>
24 #include <type_traits>
27 #include "src/core/lib/gprpp/debug_location.h"
28 #include "src/core/lib/gprpp/memory.h"
32 // A smart pointer class for objects that provide IncrementRefCount() and
33 // Unref() methods, such as those provided by the RefCounted base class.
38 RefCountedPtr(std::nullptr_t) {}
40 // If value is non-null, we take ownership of a ref to it.
42 explicit RefCountedPtr(Y* value) {
47 RefCountedPtr(RefCountedPtr&& other) {
48 value_ = other.value_;
49 other.value_ = nullptr;
52 RefCountedPtr(RefCountedPtr<Y>&& other) {
53 value_ = static_cast<T*>(other.value_);
54 other.value_ = nullptr;
58 RefCountedPtr& operator=(RefCountedPtr&& other) {
60 other.value_ = nullptr;
64 RefCountedPtr& operator=(RefCountedPtr<Y>&& other) {
66 other.value_ = nullptr;
71 RefCountedPtr(const RefCountedPtr& other) {
72 if (other.value_ != nullptr) other.value_->IncrementRefCount();
73 value_ = other.value_;
76 RefCountedPtr(const RefCountedPtr<Y>& other) {
77 static_assert(std::has_virtual_destructor<T>::value,
78 "T does not have a virtual dtor");
79 if (other.value_ != nullptr) other.value_->IncrementRefCount();
80 value_ = static_cast<T*>(other.value_);
84 RefCountedPtr& operator=(const RefCountedPtr& other) {
85 // Note: Order of reffing and unreffing is important here in case value_
86 // and other.value_ are the same object.
87 if (other.value_ != nullptr) other.value_->IncrementRefCount();
92 RefCountedPtr& operator=(const RefCountedPtr<Y>& other) {
93 static_assert(std::has_virtual_destructor<T>::value,
94 "T does not have a virtual dtor");
95 // Note: Order of reffing and unreffing is important here in case value_
96 // and other.value_ are the same object.
97 if (other.value_ != nullptr) other.value_->IncrementRefCount();
103 if (value_ != nullptr) value_->Unref();
106 void swap(RefCountedPtr& other) { std::swap(value_, other.value_); }
108 // If value is non-null, we take ownership of a ref to it.
109 void reset(T* value = nullptr) {
110 if (value_ != nullptr) value_->Unref();
113 void reset(const DebugLocation& location, const char* reason,
114 T* value = nullptr) {
115 if (value_ != nullptr) value_->Unref(location, reason);
118 template <typename Y>
119 void reset(Y* value = nullptr) {
120 static_assert(std::has_virtual_destructor<T>::value,
121 "T does not have a virtual dtor");
122 if (value_ != nullptr) value_->Unref();
123 value_ = static_cast<T*>(value);
125 template <typename Y>
126 void reset(const DebugLocation& location, const char* reason,
127 Y* value = nullptr) {
128 static_assert(std::has_virtual_destructor<T>::value,
129 "T does not have a virtual dtor");
130 if (value_ != nullptr) value_->Unref(location, reason);
131 value_ = static_cast<T*>(value);
134 // TODO(roth): This method exists solely as a transition mechanism to allow
135 // us to pass a ref to idiomatic C code that does not use RefCountedPtr<>.
136 // Once all of our code has been converted to idiomatic C++, this
137 // method should go away.
144 T* get() const { return value_; }
146 T& operator*() const { return *value_; }
147 T* operator->() const { return value_; }
149 template <typename Y>
150 bool operator==(const RefCountedPtr<Y>& other) const {
151 return value_ == other.value_;
154 template <typename Y>
155 bool operator==(const Y* other) const {
156 return value_ == other;
159 bool operator==(std::nullptr_t) const { return value_ == nullptr; }
161 template <typename Y>
162 bool operator!=(const RefCountedPtr<Y>& other) const {
163 return value_ != other.value_;
166 template <typename Y>
167 bool operator!=(const Y* other) const {
168 return value_ != other;
171 bool operator!=(std::nullptr_t) const { return value_ != nullptr; }
174 template <typename Y>
175 friend class RefCountedPtr;
180 template <typename T, typename... Args>
181 inline RefCountedPtr<T> MakeRefCounted(Args&&... args) {
182 return RefCountedPtr<T>(New<T>(std::forward<Args>(args)...));
185 } // namespace grpc_core
187 #endif /* GRPC_CORE_LIB_GPRPP_REF_COUNTED_PTR_H */