GRPC C++  1.39.1
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  // NOLINTNEXTLINE(google-explicit-constructor)
39  RefCountedPtr(std::nullptr_t) {}
40 
41  // If value is non-null, we take ownership of a ref to it.
42  template <typename Y>
43  // NOLINTNEXTLINE(google-explicit-constructor)
44  RefCountedPtr(Y* value) : value_(value) {}
45 
46  // Move ctors.
47  RefCountedPtr(RefCountedPtr&& other) noexcept {
48  value_ = other.value_;
49  other.value_ = nullptr;
50  }
51  template <typename Y>
52  // NOLINTNEXTLINE(google-explicit-constructor)
53  RefCountedPtr(RefCountedPtr<Y>&& other) noexcept {
54  value_ = static_cast<T*>(other.value_);
55  other.value_ = nullptr;
56  }
57 
58  // Move assignment.
59  RefCountedPtr& operator=(RefCountedPtr&& other) noexcept {
60  reset(other.value_);
61  other.value_ = nullptr;
62  return *this;
63  }
64  template <typename Y>
66  reset(other.value_);
67  other.value_ = nullptr;
68  return *this;
69  }
70 
71  // Copy ctors.
72  RefCountedPtr(const RefCountedPtr& other) {
73  if (other.value_ != nullptr) other.value_->IncrementRefCount();
74  value_ = other.value_;
75  }
76  template <typename Y>
77  // NOLINTNEXTLINE(google-explicit-constructor)
79  static_assert(std::has_virtual_destructor<T>::value,
80  "T does not have a virtual dtor");
81  if (other.value_ != nullptr) other.value_->IncrementRefCount();
82  value_ = static_cast<T*>(other.value_);
83  }
84 
85  // Copy assignment.
86  // NOLINTNEXTLINE(bugprone-unhandled-self-assignment)
88  // Note: Order of reffing and unreffing is important here in case value_
89  // and other.value_ are the same object.
90  if (other.value_ != nullptr) other.value_->IncrementRefCount();
91  reset(other.value_);
92  return *this;
93  }
94  template <typename Y>
96  static_assert(std::has_virtual_destructor<T>::value,
97  "T does not have a virtual dtor");
98  // Note: Order of reffing and unreffing is important here in case value_
99  // and other.value_ are the same object.
100  if (other.value_ != nullptr) other.value_->IncrementRefCount();
101  reset(other.value_);
102  return *this;
103  }
104 
106  if (value_ != nullptr) value_->Unref();
107  }
108 
109  void swap(RefCountedPtr& other) { std::swap(value_, other.value_); }
110 
111  // If value is non-null, we take ownership of a ref to it.
112  void reset(T* value = nullptr) {
113  if (value_ != nullptr) value_->Unref();
114  value_ = value;
115  }
116  void reset(const DebugLocation& location, const char* reason,
117  T* value = nullptr) {
118  if (value_ != nullptr) value_->Unref(location, reason);
119  value_ = value;
120  }
121  template <typename Y>
122  void reset(Y* value = nullptr) {
123  static_assert(std::has_virtual_destructor<T>::value,
124  "T does not have a virtual dtor");
125  if (value_ != nullptr) value_->Unref();
126  value_ = static_cast<T*>(value);
127  }
128  template <typename Y>
129  void reset(const DebugLocation& location, const char* reason,
130  Y* value = nullptr) {
131  static_assert(std::has_virtual_destructor<T>::value,
132  "T does not have a virtual dtor");
133  if (value_ != nullptr) value_->Unref(location, reason);
134  value_ = static_cast<T*>(value);
135  }
136 
137  // TODO(roth): This method exists solely as a transition mechanism to allow
138  // us to pass a ref to idiomatic C code that does not use RefCountedPtr<>.
139  // Once all of our code has been converted to idiomatic C++, this
140  // method should go away.
141  T* release() {
142  T* value = value_;
143  value_ = nullptr;
144  return value;
145  }
146 
147  T* get() const { return value_; }
148 
149  T& operator*() const { return *value_; }
150  T* operator->() const { return value_; }
151 
152  template <typename Y>
153  bool operator==(const RefCountedPtr<Y>& other) const {
154  return value_ == other.value_;
155  }
156 
157  template <typename Y>
158  bool operator==(const Y* other) const {
159  return value_ == other;
160  }
161 
162  bool operator==(std::nullptr_t) const { return value_ == nullptr; }
163 
164  template <typename Y>
165  bool operator!=(const RefCountedPtr<Y>& other) const {
166  return value_ != other.value_;
167  }
168 
169  template <typename Y>
170  bool operator!=(const Y* other) const {
171  return value_ != other;
172  }
173 
174  bool operator!=(std::nullptr_t) const { return value_ != nullptr; }
175 
176  private:
177  template <typename Y>
178  friend class RefCountedPtr;
179 
180  T* value_ = nullptr;
181 };
182 
183 // A smart pointer class for objects that provide IncrementWeakRefCount() and
184 // WeakUnref() methods, such as those provided by the DualRefCounted base class.
185 template <typename T>
187  public:
189  // NOLINTNEXTLINE(google-explicit-constructor)
190  WeakRefCountedPtr(std::nullptr_t) {}
191 
192  // If value is non-null, we take ownership of a ref to it.
193  template <typename Y>
194  // NOLINTNEXTLINE(google-explicit-constructor)
195  WeakRefCountedPtr(Y* value) {
196  value_ = value;
197  }
198 
199  // Move ctors.
201  value_ = other.value_;
202  other.value_ = nullptr;
203  }
204  template <typename Y>
205  // NOLINTNEXTLINE(google-explicit-constructor)
207  value_ = static_cast<T*>(other.value_);
208  other.value_ = nullptr;
209  }
210 
211  // Move assignment.
213  reset(other.value_);
214  other.value_ = nullptr;
215  return *this;
216  }
217  template <typename Y>
219  reset(other.value_);
220  other.value_ = nullptr;
221  return *this;
222  }
223 
224  // Copy ctors.
226  if (other.value_ != nullptr) other.value_->IncrementWeakRefCount();
227  value_ = other.value_;
228  }
229  template <typename Y>
230  // NOLINTNEXTLINE(google-explicit-constructor)
232  static_assert(std::has_virtual_destructor<T>::value,
233  "T does not have a virtual dtor");
234  if (other.value_ != nullptr) other.value_->IncrementWeakRefCount();
235  value_ = static_cast<T*>(other.value_);
236  }
237 
238  // Copy assignment.
239  // NOLINTNEXTLINE(bugprone-unhandled-self-assignment)
241  // Note: Order of reffing and unreffing is important here in case value_
242  // and other.value_ are the same object.
243  if (other.value_ != nullptr) other.value_->IncrementWeakRefCount();
244  reset(other.value_);
245  return *this;
246  }
247  template <typename Y>
249  static_assert(std::has_virtual_destructor<T>::value,
250  "T does not have a virtual dtor");
251  // Note: Order of reffing and unreffing is important here in case value_
252  // and other.value_ are the same object.
253  if (other.value_ != nullptr) other.value_->IncrementWeakRefCount();
254  reset(other.value_);
255  return *this;
256  }
257 
259  if (value_ != nullptr) value_->WeakUnref();
260  }
261 
262  void swap(WeakRefCountedPtr& other) { std::swap(value_, other.value_); }
263 
264  // If value is non-null, we take ownership of a ref to it.
265  void reset(T* value = nullptr) {
266  if (value_ != nullptr) value_->WeakUnref();
267  value_ = value;
268  }
269  void reset(const DebugLocation& location, const char* reason,
270  T* value = nullptr) {
271  if (value_ != nullptr) value_->WeakUnref(location, reason);
272  value_ = value;
273  }
274  template <typename Y>
275  void reset(Y* value = nullptr) {
276  static_assert(std::has_virtual_destructor<T>::value,
277  "T does not have a virtual dtor");
278  if (value_ != nullptr) value_->WeakUnref();
279  value_ = static_cast<T*>(value);
280  }
281  template <typename Y>
282  void reset(const DebugLocation& location, const char* reason,
283  Y* value = nullptr) {
284  static_assert(std::has_virtual_destructor<T>::value,
285  "T does not have a virtual dtor");
286  if (value_ != nullptr) value_->WeakUnref(location, reason);
287  value_ = static_cast<T*>(value);
288  }
289 
290  // TODO(roth): This method exists solely as a transition mechanism to allow
291  // us to pass a ref to idiomatic C code that does not use WeakRefCountedPtr<>.
292  // Once all of our code has been converted to idiomatic C++, this
293  // method should go away.
294  T* release() {
295  T* value = value_;
296  value_ = nullptr;
297  return value;
298  }
299 
300  T* get() const { return value_; }
301 
302  T& operator*() const { return *value_; }
303  T* operator->() const { return value_; }
304 
305  template <typename Y>
306  bool operator==(const WeakRefCountedPtr<Y>& other) const {
307  return value_ == other.value_;
308  }
309 
310  template <typename Y>
311  bool operator==(const Y* other) const {
312  return value_ == other;
313  }
314 
315  bool operator==(std::nullptr_t) const { return value_ == nullptr; }
316 
317  template <typename Y>
318  bool operator!=(const WeakRefCountedPtr<Y>& other) const {
319  return value_ != other.value_;
320  }
321 
322  template <typename Y>
323  bool operator!=(const Y* other) const {
324  return value_ != other;
325  }
326 
327  bool operator!=(std::nullptr_t) const { return value_ != nullptr; }
328 
329  private:
330  template <typename Y>
331  friend class WeakRefCountedPtr;
332 
333  T* value_ = nullptr;
334 };
335 
336 template <typename T, typename... Args>
337 inline RefCountedPtr<T> MakeRefCounted(Args&&... args) {
338  return RefCountedPtr<T>(new T(std::forward<Args>(args)...));
339 }
340 
341 template <typename T>
342 bool operator<(const RefCountedPtr<T>& p1, const RefCountedPtr<T>& p2) {
343  return p1.get() < p2.get();
344 }
345 
346 template <typename T>
348  return p1.get() < p2.get();
349 }
350 
351 } // namespace grpc_core
352 
353 #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:174
RefCountedPtr & operator=(const RefCountedPtr &other)
Definition: ref_counted_ptr.h:87
RefCountedPtr & operator=(RefCountedPtr &&other) noexcept
Definition: ref_counted_ptr.h:59
bool operator==(const Y *other) const
Definition: ref_counted_ptr.h:158
RefCountedPtr(RefCountedPtr< Y > &&other) noexcept
Definition: ref_counted_ptr.h:53
bool operator==(const RefCountedPtr< Y > &other) const
Definition: ref_counted_ptr.h:153
bool operator!=(const RefCountedPtr< Y > &other) const
Definition: ref_counted_ptr.h:165
bool operator!=(const Y *other) const
Definition: ref_counted_ptr.h:170
void reset(Y *value=nullptr)
Definition: ref_counted_ptr.h:122
RefCountedPtr & operator=(RefCountedPtr< Y > &&other) noexcept
Definition: ref_counted_ptr.h:65
T * get() const
Definition: ref_counted_ptr.h:147
T * operator->() const
Definition: ref_counted_ptr.h:150
void reset(const DebugLocation &location, const char *reason, Y *value=nullptr)
Definition: ref_counted_ptr.h:129
RefCountedPtr & operator=(const RefCountedPtr< Y > &other)
Definition: ref_counted_ptr.h:95
T * release()
Definition: ref_counted_ptr.h:141
~RefCountedPtr()
Definition: ref_counted_ptr.h:105
RefCountedPtr(const RefCountedPtr< Y > &other)
Definition: ref_counted_ptr.h:78
bool operator==(std::nullptr_t) const
Definition: ref_counted_ptr.h:162
void swap(RefCountedPtr &other)
Definition: ref_counted_ptr.h:109
RefCountedPtr(std::nullptr_t)
Definition: ref_counted_ptr.h:39
RefCountedPtr(Y *value)
Definition: ref_counted_ptr.h:44
RefCountedPtr()
Definition: ref_counted_ptr.h:37
T & operator*() const
Definition: ref_counted_ptr.h:149
void reset(const DebugLocation &location, const char *reason, T *value=nullptr)
Definition: ref_counted_ptr.h:116
void reset(T *value=nullptr)
Definition: ref_counted_ptr.h:112
RefCountedPtr(const RefCountedPtr &other)
Definition: ref_counted_ptr.h:72
RefCountedPtr(RefCountedPtr &&other) noexcept
Definition: ref_counted_ptr.h:47
Definition: ref_counted_ptr.h:186
bool operator!=(std::nullptr_t) const
Definition: ref_counted_ptr.h:327
WeakRefCountedPtr(Y *value)
Definition: ref_counted_ptr.h:195
void swap(WeakRefCountedPtr &other)
Definition: ref_counted_ptr.h:262
T * operator->() const
Definition: ref_counted_ptr.h:303
WeakRefCountedPtr & operator=(WeakRefCountedPtr< Y > &&other) noexcept
Definition: ref_counted_ptr.h:218
T * release()
Definition: ref_counted_ptr.h:294
WeakRefCountedPtr(WeakRefCountedPtr &&other) noexcept
Definition: ref_counted_ptr.h:200
bool operator!=(const Y *other) const
Definition: ref_counted_ptr.h:323
bool operator==(std::nullptr_t) const
Definition: ref_counted_ptr.h:315
WeakRefCountedPtr & operator=(WeakRefCountedPtr &&other) noexcept
Definition: ref_counted_ptr.h:212
void reset(Y *value=nullptr)
Definition: ref_counted_ptr.h:275
bool operator!=(const WeakRefCountedPtr< Y > &other) const
Definition: ref_counted_ptr.h:318
WeakRefCountedPtr & operator=(const WeakRefCountedPtr< Y > &other)
Definition: ref_counted_ptr.h:248
void reset(const DebugLocation &location, const char *reason, T *value=nullptr)
Definition: ref_counted_ptr.h:269
T & operator*() const
Definition: ref_counted_ptr.h:302
WeakRefCountedPtr()
Definition: ref_counted_ptr.h:188
WeakRefCountedPtr & operator=(const WeakRefCountedPtr &other)
Definition: ref_counted_ptr.h:240
~WeakRefCountedPtr()
Definition: ref_counted_ptr.h:258
void reset(const DebugLocation &location, const char *reason, Y *value=nullptr)
Definition: ref_counted_ptr.h:282
bool operator==(const Y *other) const
Definition: ref_counted_ptr.h:311
WeakRefCountedPtr(const WeakRefCountedPtr &other)
Definition: ref_counted_ptr.h:225
T * get() const
Definition: ref_counted_ptr.h:300
WeakRefCountedPtr(std::nullptr_t)
Definition: ref_counted_ptr.h:190
void reset(T *value=nullptr)
Definition: ref_counted_ptr.h:265
WeakRefCountedPtr(const WeakRefCountedPtr< Y > &other)
Definition: ref_counted_ptr.h:231
WeakRefCountedPtr(WeakRefCountedPtr< Y > &&other) noexcept
Definition: ref_counted_ptr.h:206
bool operator==(const WeakRefCountedPtr< Y > &other) const
Definition: ref_counted_ptr.h:306
Round Robin Policy.
Definition: backend_metric.cc:26
RefCountedPtr< T > MakeRefCounted(Args &&... args)
Definition: ref_counted_ptr.h:337
bool operator<(const RefCountedPtr< T > &p1, const RefCountedPtr< T > &p2)
Definition: ref_counted_ptr.h:342