1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef _STLPORT_CPP11_EXTENSION_MEMORY_ 18 #define _STLPORT_CPP11_EXTENSION_MEMORY_ 19 20 // This file extends stlport's <memory> implementation to provide support for: 21 // - std::shared_ptr (C++11) 22 // - std::unique_ptr (C++11) 23 24 // Cloned from master branch vendor/google/native/cmds/sysproxy/shared_ptr.h 25 // Upstream commit ff64c352c35c46a14f15503778781889a816eea4 26 // Upstream Change-Id: I481ec53b08beecde2bf6dc38e5933342235da3d9 27 28 #include <stlport/memory> 29 30 namespace std { 31 32 template <typename T> 33 class shared_ptr { 34 public: 35 shared_ptr(); 36 explicit shared_ptr(T *value); 37 shared_ptr(const shared_ptr &rhs); 38 shared_ptr &operator=(const shared_ptr &rhs); 39 template <typename U> 40 shared_ptr(const shared_ptr<U> &rhs); 41 template <typename U> 42 shared_ptr &operator=(const shared_ptr<U> &rhs); 43 ~shared_ptr(); 44 45 T *get() const; 46 T *operator->() const; 47 T &operator*() const; 48 49 template <typename U> 50 bool operator==(const shared_ptr<U> &rhs) const; 51 template <typename U> 52 bool operator!=(const shared_ptr<U> &rhs) const; 53 template <typename U> 54 bool operator<(const shared_ptr<U> &rhs) const; 55 template <typename U> 56 bool operator<=(const shared_ptr<U> &rhs) const; 57 template <typename U> 58 bool operator>(const shared_ptr<U> &rhs) const; 59 template <typename U> 60 bool operator>=(const shared_ptr<U> &rhs) const; 61 62 void reset(T *value = NULL); 63 64 // TODO(haining) Work with Deleter 65 66 private: 67 template <typename U> 68 friend class shared_ptr; 69 70 struct Node { 71 T *value; 72 int *count; 73 }; 74 // Thread safe decrement, deletes node_ if holding last remaining reference. 75 // Any use of node_ after calling this function is unsafe unless node_ is 76 // reassigned. 77 void DecNode(); 78 79 // Thread safe increment. 80 void IncNode(); 81 82 // Creates a Node referring to NULL. 83 static Node NewNullNode(); 84 85 // Creates a Node referring to value. 86 static Node NewNodeFor(T *value); 87 88 Node node_; 89 }; 90 91 template <typename T> 92 typename shared_ptr<T>::Node shared_ptr<T>::NewNodeFor(T *value) { 93 Node n = {value, new int(1)}; 94 return n; 95 } 96 97 template <typename T> 98 typename shared_ptr<T>::Node shared_ptr<T>::NewNullNode() { 99 return NewNodeFor(NULL); 100 } 101 102 template <typename T> 103 void shared_ptr<T>::reset(T *value) { 104 DecNode(); 105 node_ = NewNodeFor(value); 106 } 107 108 template <typename T> 109 shared_ptr<T>::shared_ptr() : node_(NewNullNode()) {} 110 111 template <typename T> 112 void shared_ptr<T>::DecNode() { 113 bool should_delete = __atomic_fetch_sub(node_.count, 1, __ATOMIC_SEQ_CST) == 0; 114 // The only accesses to node_ that should be made after this line is the 115 // deletion conditional on should_delete. Anything else is unsafe since 116 // because another thread could have deleted node_ 117 if (should_delete) { 118 delete node_.value; 119 delete node_.count; 120 node_.value = NULL; 121 node_.count = NULL; 122 } 123 } 124 125 template <typename T> 126 void shared_ptr<T>::IncNode() { 127 __atomic_fetch_add(node_.count, 1, __ATOMIC_SEQ_CST); 128 } 129 130 template <typename T> 131 shared_ptr<T>::shared_ptr(T *value) { 132 node_ = NewNodeFor(value); 133 } 134 135 template <typename T> 136 shared_ptr<T>::shared_ptr(const shared_ptr &rhs) : node_(rhs.node_) { 137 IncNode(); 138 } 139 140 template <typename T> 141 template <typename U> 142 shared_ptr<T>::shared_ptr(const shared_ptr<U> &rhs) { 143 node_.value = rhs.node_.value; 144 node_.count = rhs.node_.count; 145 node_.m = rhs.node_.m; 146 IncNode(); 147 } 148 149 template <typename T> 150 shared_ptr<T> &shared_ptr<T>::operator=(const shared_ptr &rhs) { 151 if (node_.value == rhs.node_.value) { 152 return *this; 153 } 154 155 DecNode(); 156 node_ = rhs.node_; 157 IncNode(); 158 return *this; 159 } 160 161 template <typename T> 162 template <typename U> 163 shared_ptr<T> &shared_ptr<T>::operator=(const shared_ptr<U> &rhs) { 164 if (node_.value == rhs.node_.value) { 165 return *this; 166 } 167 168 DecNode(); 169 node_.value = rhs.node_.value; 170 node_.count = rhs.node_.count; 171 node_.m = rhs.node_.m; 172 IncNode(); 173 return *this; 174 } 175 176 template <typename T> 177 shared_ptr<T>::~shared_ptr() { 178 DecNode(); 179 } 180 181 template <typename T> 182 T *shared_ptr<T>::get() const { 183 return node_.value; 184 } 185 186 template <typename T> 187 T *shared_ptr<T>::operator->() const { 188 return get(); 189 } 190 191 template <typename T> 192 T &shared_ptr<T>::operator*() const { 193 return *node_.value; 194 } 195 196 template <typename T> 197 template <typename U> 198 bool shared_ptr<T>::operator==(const shared_ptr<U> &rhs) const { 199 return node_.value == rhs.node_.value; 200 } 201 202 template <typename T> 203 template <typename U> 204 bool shared_ptr<T>::operator!=(const shared_ptr<U> &rhs) const { 205 return node_.value != rhs.node_.value; 206 } 207 208 template <typename T> 209 template <typename U> 210 bool shared_ptr<T>::operator<(const shared_ptr<U> &rhs) const { 211 return node_.value < rhs.node_.value; 212 } 213 214 template <typename T> 215 template <typename U> 216 bool shared_ptr<T>::operator<=(const shared_ptr<U> &rhs) const { 217 return node_.value <= rhs.node_.value; 218 } 219 220 template <typename T> 221 template <typename U> 222 bool shared_ptr<T>::operator>(const shared_ptr<U> &rhs) const { 223 return node_.value > rhs.node_.value; 224 } 225 226 template <typename T> 227 template <typename U> 228 bool shared_ptr<T>::operator>=(const shared_ptr<U> &rhs) const { 229 return node_.value >= rhs.node_.value; 230 } 231 232 #if !defined(DISALLOW_COPY_AND_ASSIGN) 233 #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ 234 TypeName(const TypeName&); \ 235 void operator=(const TypeName&); 236 #endif 237 238 #include <cstddef> 239 240 // Default deleter for pointer types. 241 template <typename T> 242 struct DefaultDelete { 243 void operator()(T* p) const { delete p; } 244 }; 245 246 // Default deleter for array types. 247 template <typename T> 248 struct DefaultDelete<T[]> { 249 void operator()(T* p) const { delete[] p; } 250 }; 251 252 // A smart pointer that deletes the given pointer on destruction. 253 // Equivalent to C++11's std::unique_ptr 254 // Named to be in keeping with Android style but also to avoid 255 // collision with any other implementation, until we can switch over 256 // to unique_ptr. 257 // Use thus: 258 // unique_ptr<C> c(new C); 259 260 namespace workaround_internal { 261 template <typename T, typename Deleter> 262 class UniquePtrBase { 263 public: 264 // Construct a new UniquePtrBase, taking ownership of the given raw pointer. 265 explicit UniquePtrBase(T* ptr = 0) : mPtr(ptr), mDeleter() {} 266 explicit UniquePtrBase(T* ptr, Deleter d) : mPtr(ptr), mDeleter(d) {} 267 268 ~UniquePtrBase() { reset(); } 269 270 // Accessors. 271 T* get() const { return mPtr; } 272 273 // Returns the raw pointer and hands over ownership to the caller. 274 // The pointer will not be deleted by UniquePtrBase. 275 T* release() { 276 T* result = mPtr; 277 mPtr = 0; 278 return result; 279 } 280 281 // Takes ownership of the given raw pointer. 282 // If this smart pointer previously owned a different raw pointer, that 283 // raw pointer will be freed. 284 void reset(T* ptr = 0) { 285 T* old_ptr = mPtr; 286 mPtr = ptr; 287 if (old_ptr != NULL && mPtr != old_ptr) { 288 get_deleter()(old_ptr); 289 } 290 } 291 292 Deleter& get_deleter() { return mDeleter; } 293 const Deleter& get_deleter() const { return mDeleter; } 294 295 private: 296 // This is so users can compare against null. Callers should be able 297 // to invoke operator== and operator!= above with NULL pointers but not 298 // with any other pointer. 299 struct RawDummy {}; 300 301 public: 302 bool operator==(const RawDummy*) const { return get() == NULL; } 303 friend bool operator==(const RawDummy*, const UniquePtrBase& self) { 304 return self == NULL; 305 } 306 307 bool operator!=(const RawDummy*) const { return !(*this == NULL); } 308 friend bool operator!=(const RawDummy*, const UniquePtrBase& self) { 309 return self != NULL; 310 } 311 312 private: 313 // The raw pointer. 314 T* mPtr; 315 Deleter mDeleter; 316 317 DISALLOW_COPY_AND_ASSIGN(UniquePtrBase); 318 }; 319 } // namespace workaround_internal 320 321 template <typename T, typename Deleter = DefaultDelete<T> > 322 class unique_ptr : public workaround_internal::UniquePtrBase<T, Deleter> { 323 typedef workaround_internal::UniquePtrBase<T, Deleter> Base; 324 public: 325 // Construct a new unique_ptr, taking ownership of the given raw pointer. 326 explicit unique_ptr(T* ptr = 0) : Base(ptr) { } 327 explicit unique_ptr(T* ptr, Deleter d) : Base(ptr, d) { } 328 329 T& operator*() const { return *this->get(); } 330 T* operator->() const { return this->get(); } 331 }; 332 333 // Partial specialization for array types. Like std::unique_ptr, this removes 334 // operator* and operator-> but adds operator[]. 335 template <typename T, typename Deleter> 336 class unique_ptr<T[], Deleter> : public workaround_internal::UniquePtrBase<T, Deleter> { 337 typedef workaround_internal::UniquePtrBase<T, Deleter> Base; 338 public: 339 explicit unique_ptr(T* ptr = 0) : Base(ptr) { } 340 explicit unique_ptr(T* ptr, Deleter d) : Base(ptr, d) { } 341 342 T& operator[](std::ptrdiff_t i) const { return this->get()[i]; } 343 }; 344 345 template <typename T> 346 shared_ptr<T> make_shared() { 347 return shared_ptr<T>(new T); 348 } 349 350 } // namespace std 351 352 #endif // _STLPORT_CPP11_EXTENSION_MEMORY_ 353