Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc-cloned / deps / grpc / src / core / lib / gprpp / ref_counted_ptr.h
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 <type_traits>
25 #include <utility>
26
27 #include "src/core/lib/gprpp/debug_location.h"
28 #include "src/core/lib/gprpp/memory.h"
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>
35 class RefCountedPtr {
36  public:
37   RefCountedPtr() {}
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.
47   RefCountedPtr(RefCountedPtr&& other) {
48     value_ = other.value_;
49     other.value_ = nullptr;
50   }
51   template <typename Y>
52   RefCountedPtr(RefCountedPtr<Y>&& other) {
53     value_ = static_cast<T*>(other.value_);
54     other.value_ = nullptr;
55   }
56
57   // Move assignment.
58   RefCountedPtr& operator=(RefCountedPtr&& other) {
59     reset(other.value_);
60     other.value_ = nullptr;
61     return *this;
62   }
63   template <typename Y>
64   RefCountedPtr& operator=(RefCountedPtr<Y>&& other) {
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>
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_);
81   }
82
83   // Copy assignment.
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();
88     reset(other.value_);
89     return *this;
90   }
91   template <typename Y>
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();
98     reset(other.value_);
99     return *this;
100   }
101
102   ~RefCountedPtr() {
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 */