GRPC Core  9.0.0
ref_counted_ptr.h
Go to the documentation of this file.
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 
23 
24 #include <type_traits>
25 #include <utility>
26 
29 
30 namespace grpc_core {
31 
32 // A smart pointer class for objects that provide IncrementRefCount() and
33 // Unref() methods, such as those provided by the RefCounted base class.
34 template <typename T>
36  public:
38  RefCountedPtr(std::nullptr_t) {}
39 
40  // If value is non-null, we take ownership of a ref to it.
41  template <typename Y>
42  explicit RefCountedPtr(Y* value) {
43  value_ = value;
44  }
45 
46  // Move ctors.
48  value_ = other.value_;
49  other.value_ = nullptr;
50  }
51  template <typename Y>
53  value_ = static_cast<T*>(other.value_);
54  other.value_ = nullptr;
55  }
56 
57  // Move assignment.
59  reset(other.value_);
60  other.value_ = nullptr;
61  return *this;
62  }
63  template <typename Y>
65  reset(other.value_);
66  other.value_ = nullptr;
67  return *this;
68  }
69 
70  // Copy ctors.
71  RefCountedPtr(const RefCountedPtr& other) {
72  if (other.value_ != nullptr) other.value_->IncrementRefCount();
73  value_ = other.value_;
74  }
75  template <typename Y>
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_);
81  }
82 
83  // Copy assignment.
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();
88  reset(other.value_);
89  return *this;
90  }
91  template <typename Y>
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();
98  reset(other.value_);
99  return *this;
100  }
101 
103  if (value_ != nullptr) value_->Unref();
104  }
105 
106  void swap(RefCountedPtr& other) { std::swap(value_, other.value_); }
107 
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();
111  value_ = value;
112  }
113  void reset(const DebugLocation& location, const char* reason,
114  T* value = nullptr) {
115  if (value_ != nullptr) value_->Unref(location, reason);
116  value_ = value;
117  }
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);
124  }
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);
132  }
133 
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.
138  T* release() {
139  T* value = value_;
140  value_ = nullptr;
141  return value;
142  }
143 
144  T* get() const { return value_; }
145 
146  T& operator*() const { return *value_; }
147  T* operator->() const { return value_; }
148 
149  template <typename Y>
150  bool operator==(const RefCountedPtr<Y>& other) const {
151  return value_ == other.value_;
152  }
153 
154  template <typename Y>
155  bool operator==(const Y* other) const {
156  return value_ == other;
157  }
158 
159  bool operator==(std::nullptr_t) const { return value_ == nullptr; }
160 
161  template <typename Y>
162  bool operator!=(const RefCountedPtr<Y>& other) const {
163  return value_ != other.value_;
164  }
165 
166  template <typename Y>
167  bool operator!=(const Y* other) const {
168  return value_ != other;
169  }
170 
171  bool operator!=(std::nullptr_t) const { return value_ != nullptr; }
172 
173  private:
174  template <typename Y>
175  friend class RefCountedPtr;
176 
177  T* value_ = nullptr;
178 };
179 
180 template <typename T, typename... Args>
181 inline RefCountedPtr<T> MakeRefCounted(Args&&... args) {
182  return RefCountedPtr<T>(new T(std::forward<Args>(args)...));
183 }
184 
185 } // namespace grpc_core
186 
187 #endif /* GRPC_CORE_LIB_GPRPP_REF_COUNTED_PTR_H */
Definition: debug_location.h:31
Definition: ref_counted_ptr.h:35
bool operator!=(std::nullptr_t) const
Definition: ref_counted_ptr.h:171
RefCountedPtr & operator=(const RefCountedPtr &other)
Definition: ref_counted_ptr.h:84
bool operator==(const Y *other) const
Definition: ref_counted_ptr.h:155
RefCountedPtr(RefCountedPtr &&other)
Definition: ref_counted_ptr.h:47
bool operator==(const RefCountedPtr< Y > &other) const
Definition: ref_counted_ptr.h:150
bool operator!=(const RefCountedPtr< Y > &other) const
Definition: ref_counted_ptr.h:162
bool operator!=(const Y *other) const
Definition: ref_counted_ptr.h:167
void reset(Y *value=nullptr)
Definition: ref_counted_ptr.h:119
T * get() const
Definition: ref_counted_ptr.h:144
T * operator->() const
Definition: ref_counted_ptr.h:147
void reset(const DebugLocation &location, const char *reason, Y *value=nullptr)
Definition: ref_counted_ptr.h:126
RefCountedPtr & operator=(const RefCountedPtr< Y > &other)
Definition: ref_counted_ptr.h:92
RefCountedPtr & operator=(RefCountedPtr &&other)
Definition: ref_counted_ptr.h:58
T * release()
Definition: ref_counted_ptr.h:138
~RefCountedPtr()
Definition: ref_counted_ptr.h:102
RefCountedPtr(const RefCountedPtr< Y > &other)
Definition: ref_counted_ptr.h:76
bool operator==(std::nullptr_t) const
Definition: ref_counted_ptr.h:159
void swap(RefCountedPtr &other)
Definition: ref_counted_ptr.h:106
RefCountedPtr(RefCountedPtr< Y > &&other)
Definition: ref_counted_ptr.h:52
RefCountedPtr(std::nullptr_t)
Definition: ref_counted_ptr.h:38
RefCountedPtr(Y *value)
Definition: ref_counted_ptr.h:42
RefCountedPtr()
Definition: ref_counted_ptr.h:37
T & operator*() const
Definition: ref_counted_ptr.h:146
void reset(const DebugLocation &location, const char *reason, T *value=nullptr)
Definition: ref_counted_ptr.h:113
RefCountedPtr & operator=(RefCountedPtr< Y > &&other)
Definition: ref_counted_ptr.h:64
void reset(T *value=nullptr)
Definition: ref_counted_ptr.h:109
RefCountedPtr(const RefCountedPtr &other)
Definition: ref_counted_ptr.h:71
Round Robin Policy.
Definition: backend_metric.cc:24
RefCountedPtr< T > MakeRefCounted(Args &&... args)
Definition: ref_counted_ptr.h:181