1 /* 2 * 3 * Copyright 2017 gRPC authors. 4 * 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 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 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. 16 * 17 */ 18 19 #ifndef GRPC_CORE_LIB_GPRPP_REF_COUNTED_PTR_H 20 #define GRPC_CORE_LIB_GPRPP_REF_COUNTED_PTR_H 21 22 #include <grpc/support/port_platform.h> 23 24 #include <utility> 25 26 #include "src/core/lib/gprpp/memory.h" 27 28 namespace grpc_core { 29 30 // A smart pointer class for objects that provide IncrementRefCount() and 31 // Unref() methods, such as those provided by the RefCounted base class. 32 template <typename T> 33 class RefCountedPtr { 34 public: RefCountedPtr()35 RefCountedPtr() {} RefCountedPtr(std::nullptr_t)36 RefCountedPtr(std::nullptr_t) {} 37 38 // If value is non-null, we take ownership of a ref to it. 39 template <typename Y> RefCountedPtr(Y * value)40 explicit RefCountedPtr(Y* value) { 41 value_ = value; 42 } 43 44 // Move ctors. RefCountedPtr(RefCountedPtr && other)45 RefCountedPtr(RefCountedPtr&& other) { 46 value_ = other.value_; 47 other.value_ = nullptr; 48 } 49 template <typename Y> RefCountedPtr(RefCountedPtr<Y> && other)50 RefCountedPtr(RefCountedPtr<Y>&& other) { 51 value_ = other.value_; 52 other.value_ = nullptr; 53 } 54 55 // Move assignment. 56 RefCountedPtr& operator=(RefCountedPtr&& other) { 57 if (value_ != nullptr) value_->Unref(); 58 value_ = other.value_; 59 other.value_ = nullptr; 60 return *this; 61 } 62 template <typename Y> 63 RefCountedPtr& operator=(RefCountedPtr<Y>&& other) { 64 if (value_ != nullptr) value_->Unref(); 65 value_ = other.value_; 66 other.value_ = nullptr; 67 return *this; 68 } 69 70 // Copy ctors. RefCountedPtr(const RefCountedPtr & other)71 RefCountedPtr(const RefCountedPtr& other) { 72 if (other.value_ != nullptr) other.value_->IncrementRefCount(); 73 value_ = other.value_; 74 } 75 template <typename Y> RefCountedPtr(const RefCountedPtr<Y> & other)76 RefCountedPtr(const RefCountedPtr<Y>& other) { 77 if (other.value_ != nullptr) other.value_->IncrementRefCount(); 78 value_ = other.value_; 79 } 80 81 // Copy assignment. 82 RefCountedPtr& operator=(const RefCountedPtr& other) { 83 // Note: Order of reffing and unreffing is important here in case value_ 84 // and other.value_ are the same object. 85 if (other.value_ != nullptr) other.value_->IncrementRefCount(); 86 if (value_ != nullptr) value_->Unref(); 87 value_ = other.value_; 88 return *this; 89 } 90 template <typename Y> 91 RefCountedPtr& operator=(const RefCountedPtr<Y>& other) { 92 // Note: Order of reffing and unreffing is important here in case value_ 93 // and other.value_ are the same object. 94 if (other.value_ != nullptr) other.value_->IncrementRefCount(); 95 if (value_ != nullptr) value_->Unref(); 96 value_ = other.value_; 97 return *this; 98 } 99 ~RefCountedPtr()100 ~RefCountedPtr() { 101 if (value_ != nullptr) value_->Unref(); 102 } 103 104 // If value is non-null, we take ownership of a ref to it. 105 template <typename Y> reset(Y * value)106 void reset(Y* value) { 107 if (value_ != nullptr) value_->Unref(); 108 value_ = value; 109 } 110 reset()111 void reset() { 112 if (value_ != nullptr) value_->Unref(); 113 value_ = nullptr; 114 } 115 116 // TODO(roth): This method exists solely as a transition mechanism to allow 117 // us to pass a ref to idiomatic C code that does not use RefCountedPtr<>. 118 // Once all of our code has been converted to idiomatic C++, this 119 // method should go away. release()120 T* release() { 121 T* value = value_; 122 value_ = nullptr; 123 return value; 124 } 125 get()126 T* get() const { return value_; } 127 128 T& operator*() const { return *value_; } 129 T* operator->() const { return value_; } 130 131 template <typename Y> 132 bool operator==(const RefCountedPtr<Y>& other) const { 133 return value_ == other.value_; 134 } 135 136 template <typename Y> 137 bool operator==(const Y* other) const { 138 return value_ == other; 139 } 140 141 bool operator==(std::nullptr_t) const { return value_ == nullptr; } 142 143 template <typename Y> 144 bool operator!=(const RefCountedPtr<Y>& other) const { 145 return value_ != other.value_; 146 } 147 148 template <typename Y> 149 bool operator!=(const Y* other) const { 150 return value_ != other; 151 } 152 153 bool operator!=(std::nullptr_t) const { return value_ != nullptr; } 154 155 private: 156 template <typename Y> 157 friend class RefCountedPtr; 158 159 T* value_ = nullptr; 160 }; 161 162 template <typename T, typename... Args> MakeRefCounted(Args &&...args)163inline RefCountedPtr<T> MakeRefCounted(Args&&... args) { 164 return RefCountedPtr<T>(New<T>(std::forward<Args>(args)...)); 165 } 166 167 } // namespace grpc_core 168 169 #endif /* GRPC_CORE_LIB_GPRPP_REF_COUNTED_PTR_H */ 170