| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Scopers help you manage ownership of a pointer, helping you easily manage the | 5 // Scopers help you manage ownership of a pointer, helping you easily manage the |
| 6 // a pointer within a scope, and automatically destroying the pointer at the | 6 // a pointer within a scope, and automatically destroying the pointer at the |
| 7 // end of a scope. There are two main classes you will use, which correspond | 7 // end of a scope. There are two main classes you will use, which correspond |
| 8 // to the operators new/delete and new[]/delete[]. | 8 // to the operators new/delete and new[]/delete[]. |
| 9 // | 9 // |
| 10 // Example usage (scoped_ptr): | 10 // Example usage (scoped_ptr): |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 | 74 |
| 75 // This is an implementation designed to match the anticipated future TR2 | 75 // This is an implementation designed to match the anticipated future TR2 |
| 76 // implementation of the scoped_ptr class, and its closely-related brethren, | 76 // implementation of the scoped_ptr class, and its closely-related brethren, |
| 77 // scoped_array, scoped_ptr_malloc. | 77 // scoped_array, scoped_ptr_malloc. |
| 78 | 78 |
| 79 #include <assert.h> | 79 #include <assert.h> |
| 80 #include <stddef.h> | 80 #include <stddef.h> |
| 81 #include <stdlib.h> | 81 #include <stdlib.h> |
| 82 | 82 |
| 83 #include "base/compiler_specific.h" | 83 #include "base/compiler_specific.h" |
| 84 | 84 #include "base/move.h" |
| 85 // Macro with the boilerplate C++03 move emulation for a class. | |
| 86 // | |
| 87 // In C++11, this is done via rvalue references. Here, we use C++03 move | |
| 88 // emulation to fake an rvalue reference. For a more thorough explanation | |
| 89 // of the technique, see: | |
| 90 // | |
| 91 // http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor | |
| 92 // | |
| 93 #define CPP_03_MOVE_EMULATION(scoper, field) \ | |
| 94 private: \ | |
| 95 struct RValue { \ | |
| 96 explicit RValue(scoper& obj) : obj_(obj) {} \ | |
| 97 scoper& obj_; \ | |
| 98 }; \ | |
| 99 public: \ | |
| 100 operator RValue() { return RValue(*this); } \ | |
| 101 scoper(RValue proxy) : field(proxy.obj_.release()) { } \ | |
| 102 scoper& operator=(RValue proxy) { \ | |
| 103 swap(proxy.obj_); \ | |
| 104 return *this; \ | |
| 105 } \ | |
| 106 scoper Pass() { return scoper(RValue(*this)); } | |
| 107 | 85 |
| 108 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> | 86 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> |
| 109 // automatically deletes the pointer it holds (if any). | 87 // automatically deletes the pointer it holds (if any). |
| 110 // That is, scoped_ptr<T> owns the T object that it points to. | 88 // That is, scoped_ptr<T> owns the T object that it points to. |
| 111 // Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. | 89 // Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. |
| 112 // Also like T*, scoped_ptr<T> is thread-compatible, and once you | 90 // Also like T*, scoped_ptr<T> is thread-compatible, and once you |
| 113 // dereference it, you get the thread safety guarantees of T. | 91 // dereference it, you get the thread safety guarantees of T. |
| 114 // | 92 // |
| 115 // The size of a scoped_ptr is small: | 93 // The size of a scoped_ptr is small: |
| 116 // sizeof(scoped_ptr<C>) == sizeof(C*) | 94 // sizeof(scoped_ptr<C>) == sizeof(C*) |
| 117 template <class C> | 95 template <class C> |
| 118 class scoped_ptr { | 96 class scoped_ptr { |
| 97 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue); |
| 98 |
| 119 public: | 99 public: |
| 120 | 100 |
| 121 // The element type | 101 // The element type |
| 122 typedef C element_type; | 102 typedef C element_type; |
| 123 | 103 |
| 124 // Constructor. Defaults to initializing with NULL. | 104 // Constructor. Defaults to initializing with NULL. |
| 125 // There is no way to create an uninitialized scoped_ptr. | 105 // There is no way to create an uninitialized scoped_ptr. |
| 126 // The input parameter must be allocated with new. | 106 // The input parameter must be allocated with new. |
| 127 explicit scoped_ptr(C* p = NULL) : ptr_(p) { } | 107 explicit scoped_ptr(C* p = NULL) : ptr_(p) { } |
| 128 | 108 |
| 129 // Constructor. Allows construction from a scoped_ptr rvalue for a | 109 // Constructor. Allows construction from a scoped_ptr rvalue for a |
| 130 // convertible type. | 110 // convertible type. |
| 131 template <typename U> | 111 template <typename U> |
| 132 scoped_ptr(scoped_ptr<U> other) : ptr_(other.release()) { | 112 scoped_ptr(scoped_ptr<U> other) : ptr_(other.release()) { } |
| 133 } | 113 |
| 114 // Constructor. Move constructor for C++03 move emulation of this type. |
| 115 scoped_ptr(RValue& other) : ptr_(other.release()) { } |
| 134 | 116 |
| 135 // Destructor. If there is a C object, delete it. | 117 // Destructor. If there is a C object, delete it. |
| 136 // We don't need to test ptr_ == NULL because C++ does that for us. | 118 // We don't need to test ptr_ == NULL because C++ does that for us. |
| 137 ~scoped_ptr() { | 119 ~scoped_ptr() { |
| 138 enum { type_must_be_complete = sizeof(C) }; | 120 enum { type_must_be_complete = sizeof(C) }; |
| 139 delete ptr_; | 121 delete ptr_; |
| 140 } | 122 } |
| 141 | 123 |
| 142 // operator=. Allows assignment from a scoped_ptr rvalue for a convertible | 124 // operator=. Allows assignment from a scoped_ptr rvalue for a convertible |
| 143 // type. | 125 // type. |
| 144 template <typename U> | 126 template <typename U> |
| 145 scoped_ptr& operator=(scoped_ptr<U> rhs) { | 127 scoped_ptr& operator=(scoped_ptr<U> rhs) { |
| 146 reset(rhs.release()); | 128 reset(rhs.release()); |
| 147 return *this; | 129 return *this; |
| 148 } | 130 } |
| 149 | 131 |
| 132 // operator=. Move operator= for C++03 move emulation of this type. |
| 133 scoped_ptr& operator=(RValue& rhs) { |
| 134 swap(rhs); |
| 135 return *this; |
| 136 } |
| 137 |
| 150 // Reset. Deletes the current owned object, if any. | 138 // Reset. Deletes the current owned object, if any. |
| 151 // Then takes ownership of a new object, if given. | 139 // Then takes ownership of a new object, if given. |
| 152 // this->reset(this->get()) works. | 140 // this->reset(this->get()) works. |
| 153 void reset(C* p = NULL) { | 141 void reset(C* p = NULL) { |
| 154 if (p != ptr_) { | 142 if (p != ptr_) { |
| 155 enum { type_must_be_complete = sizeof(C) }; | 143 enum { type_must_be_complete = sizeof(C) }; |
| 156 delete ptr_; | 144 delete ptr_; |
| 157 ptr_ = p; | 145 ptr_ = p; |
| 158 } | 146 } |
| 159 } | 147 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 187 // The return value is the current pointer held by this object. | 175 // The return value is the current pointer held by this object. |
| 188 // If this object holds a NULL pointer, the return value is NULL. | 176 // If this object holds a NULL pointer, the return value is NULL. |
| 189 // After this operation, this object will hold a NULL pointer, | 177 // After this operation, this object will hold a NULL pointer, |
| 190 // and will not own the object any more. | 178 // and will not own the object any more. |
| 191 C* release() WARN_UNUSED_RESULT { | 179 C* release() WARN_UNUSED_RESULT { |
| 192 C* retVal = ptr_; | 180 C* retVal = ptr_; |
| 193 ptr_ = NULL; | 181 ptr_ = NULL; |
| 194 return retVal; | 182 return retVal; |
| 195 } | 183 } |
| 196 | 184 |
| 197 CPP_03_MOVE_EMULATION(scoped_ptr, ptr_); | |
| 198 | |
| 199 private: | 185 private: |
| 200 C* ptr_; | 186 C* ptr_; |
| 201 | 187 |
| 202 // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't | 188 // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't |
| 203 // make sense, and if C2 == C, it still doesn't make sense because you should | 189 // make sense, and if C2 == C, it still doesn't make sense because you should |
| 204 // never have the same object owned by two different scoped_ptrs. | 190 // never have the same object owned by two different scoped_ptrs. |
| 205 template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; | 191 template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; |
| 206 template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; | 192 template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; |
| 207 | 193 |
| 208 // Disallow evil constructors. Note that MUST NOT take a const& because we | |
| 209 // are implementing move semantics. See the CPP_03_MOVE_EMULATION macro. | |
| 210 scoped_ptr(scoped_ptr&); | |
| 211 void operator=(scoped_ptr&); | |
| 212 }; | 194 }; |
| 213 | 195 |
| 214 // Free functions | 196 // Free functions |
| 215 template <class C> | 197 template <class C> |
| 216 void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) { | 198 void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) { |
| 217 p1.swap(p2); | 199 p1.swap(p2); |
| 218 } | 200 } |
| 219 | 201 |
| 220 template <class C> | 202 template <class C> |
| 221 bool operator==(C* p1, const scoped_ptr<C>& p2) { | 203 bool operator==(C* p1, const scoped_ptr<C>& p2) { |
| 222 return p1 == p2.get(); | 204 return p1 == p2.get(); |
| 223 } | 205 } |
| 224 | 206 |
| 225 template <class C> | 207 template <class C> |
| 226 bool operator!=(C* p1, const scoped_ptr<C>& p2) { | 208 bool operator!=(C* p1, const scoped_ptr<C>& p2) { |
| 227 return p1 != p2.get(); | 209 return p1 != p2.get(); |
| 228 } | 210 } |
| 229 | 211 |
| 230 // scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate | 212 // scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate |
| 231 // with new [] and the destructor deletes objects with delete []. | 213 // with new [] and the destructor deletes objects with delete []. |
| 232 // | 214 // |
| 233 // As with scoped_ptr<C>, a scoped_array<C> either points to an object | 215 // As with scoped_ptr<C>, a scoped_array<C> either points to an object |
| 234 // or is NULL. A scoped_array<C> owns the object that it points to. | 216 // or is NULL. A scoped_array<C> owns the object that it points to. |
| 235 // scoped_array<T> is thread-compatible, and once you index into it, | 217 // scoped_array<T> is thread-compatible, and once you index into it, |
| 236 // the returned objects have only the thread safety guarantees of T. | 218 // the returned objects have only the thread safety guarantees of T. |
| 237 // | 219 // |
| 238 // Size: sizeof(scoped_array<C>) == sizeof(C*) | 220 // Size: sizeof(scoped_array<C>) == sizeof(C*) |
| 239 template <class C> | 221 template <class C> |
| 240 class scoped_array { | 222 class scoped_array { |
| 223 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_array, RValue); |
| 224 |
| 241 public: | 225 public: |
| 242 | 226 |
| 243 // The element type | 227 // The element type |
| 244 typedef C element_type; | 228 typedef C element_type; |
| 245 | 229 |
| 246 // Constructor. Defaults to initializing with NULL. | 230 // Constructor. Defaults to initializing with NULL. |
| 247 // There is no way to create an uninitialized scoped_array. | 231 // There is no way to create an uninitialized scoped_array. |
| 248 // The input parameter must be allocated with new []. | 232 // The input parameter must be allocated with new []. |
| 249 explicit scoped_array(C* p = NULL) : array_(p) { } | 233 explicit scoped_array(C* p = NULL) : array_(p) { } |
| 250 | 234 |
| 235 // Constructor. Move constructor for C++03 move emulation of this type. |
| 236 scoped_array(RValue& other) : array_(other.release()) { } |
| 237 |
| 251 // Destructor. If there is a C object, delete it. | 238 // Destructor. If there is a C object, delete it. |
| 252 // We don't need to test ptr_ == NULL because C++ does that for us. | 239 // We don't need to test ptr_ == NULL because C++ does that for us. |
| 253 ~scoped_array() { | 240 ~scoped_array() { |
| 254 enum { type_must_be_complete = sizeof(C) }; | 241 enum { type_must_be_complete = sizeof(C) }; |
| 255 delete[] array_; | 242 delete[] array_; |
| 256 } | 243 } |
| 257 | 244 |
| 245 // operator=. Move operator= for C++03 move emulation of this type. |
| 246 scoped_array& operator=(RValue& rhs) { |
| 247 swap(rhs); |
| 248 return *this; |
| 249 } |
| 250 |
| 258 // Reset. Deletes the current owned object, if any. | 251 // Reset. Deletes the current owned object, if any. |
| 259 // Then takes ownership of a new object, if given. | 252 // Then takes ownership of a new object, if given. |
| 260 // this->reset(this->get()) works. | 253 // this->reset(this->get()) works. |
| 261 void reset(C* p = NULL) { | 254 void reset(C* p = NULL) { |
| 262 if (p != array_) { | 255 if (p != array_) { |
| 263 enum { type_must_be_complete = sizeof(C) }; | 256 enum { type_must_be_complete = sizeof(C) }; |
| 264 delete[] array_; | 257 delete[] array_; |
| 265 array_ = p; | 258 array_ = p; |
| 266 } | 259 } |
| 267 } | 260 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 297 // The return value is the current pointer held by this object. | 290 // The return value is the current pointer held by this object. |
| 298 // If this object holds a NULL pointer, the return value is NULL. | 291 // If this object holds a NULL pointer, the return value is NULL. |
| 299 // After this operation, this object will hold a NULL pointer, | 292 // After this operation, this object will hold a NULL pointer, |
| 300 // and will not own the object any more. | 293 // and will not own the object any more. |
| 301 C* release() WARN_UNUSED_RESULT { | 294 C* release() WARN_UNUSED_RESULT { |
| 302 C* retVal = array_; | 295 C* retVal = array_; |
| 303 array_ = NULL; | 296 array_ = NULL; |
| 304 return retVal; | 297 return retVal; |
| 305 } | 298 } |
| 306 | 299 |
| 307 CPP_03_MOVE_EMULATION(scoped_array, array_); | |
| 308 | |
| 309 private: | 300 private: |
| 310 C* array_; | 301 C* array_; |
| 311 | 302 |
| 312 // Forbid comparison of different scoped_array types. | 303 // Forbid comparison of different scoped_array types. |
| 313 template <class C2> bool operator==(scoped_array<C2> const& p2) const; | 304 template <class C2> bool operator==(scoped_array<C2> const& p2) const; |
| 314 template <class C2> bool operator!=(scoped_array<C2> const& p2) const; | 305 template <class C2> bool operator!=(scoped_array<C2> const& p2) const; |
| 315 | |
| 316 // Disallow evil constructors. Note that MUST NOT take a const& because we | |
| 317 // are implementing move semantics. See the CPP_03_MOVE_EMULATION macro. | |
| 318 scoped_array(scoped_array&); | |
| 319 void operator=(scoped_array&); | |
| 320 }; | 306 }; |
| 321 | 307 |
| 322 // Free functions | 308 // Free functions |
| 323 template <class C> | 309 template <class C> |
| 324 void swap(scoped_array<C>& p1, scoped_array<C>& p2) { | 310 void swap(scoped_array<C>& p1, scoped_array<C>& p2) { |
| 325 p1.swap(p2); | 311 p1.swap(p2); |
| 326 } | 312 } |
| 327 | 313 |
| 328 template <class C> | 314 template <class C> |
| 329 bool operator==(C* p1, const scoped_array<C>& p2) { | 315 bool operator==(C* p1, const scoped_array<C>& p2) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 342 inline void operator()(void* x) const { | 328 inline void operator()(void* x) const { |
| 343 free(x); | 329 free(x); |
| 344 } | 330 } |
| 345 }; | 331 }; |
| 346 | 332 |
| 347 // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a | 333 // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a |
| 348 // second template argument, the functor used to free the object. | 334 // second template argument, the functor used to free the object. |
| 349 | 335 |
| 350 template<class C, class FreeProc = ScopedPtrMallocFree> | 336 template<class C, class FreeProc = ScopedPtrMallocFree> |
| 351 class scoped_ptr_malloc { | 337 class scoped_ptr_malloc { |
| 338 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr_malloc, RValue); |
| 339 |
| 352 public: | 340 public: |
| 353 | 341 |
| 354 // The element type | 342 // The element type |
| 355 typedef C element_type; | 343 typedef C element_type; |
| 356 | 344 |
| 357 // Constructor. Defaults to initializing with NULL. | 345 // Constructor. Defaults to initializing with NULL. |
| 358 // There is no way to create an uninitialized scoped_ptr. | 346 // There is no way to create an uninitialized scoped_ptr. |
| 359 // The input parameter must be allocated with an allocator that matches the | 347 // The input parameter must be allocated with an allocator that matches the |
| 360 // Free functor. For the default Free functor, this is malloc, calloc, or | 348 // Free functor. For the default Free functor, this is malloc, calloc, or |
| 361 // realloc. | 349 // realloc. |
| 362 explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {} | 350 explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {} |
| 363 | 351 |
| 352 // Constructor. Move constructor for C++03 move emulation of this type. |
| 353 scoped_ptr_malloc(RValue& other) : ptr_(other.release()) { } |
| 354 |
| 364 // Destructor. If there is a C object, call the Free functor. | 355 // Destructor. If there is a C object, call the Free functor. |
| 365 ~scoped_ptr_malloc() { | 356 ~scoped_ptr_malloc() { |
| 366 reset(); | 357 reset(); |
| 367 } | 358 } |
| 368 | 359 |
| 360 // operator=. Move operator= for C++03 move emulation of this type. |
| 361 scoped_ptr_malloc& operator=(RValue& rhs) { |
| 362 swap(rhs); |
| 363 return *this; |
| 364 } |
| 365 |
| 369 // Reset. Calls the Free functor on the current owned object, if any. | 366 // Reset. Calls the Free functor on the current owned object, if any. |
| 370 // Then takes ownership of a new object, if given. | 367 // Then takes ownership of a new object, if given. |
| 371 // this->reset(this->get()) works. | 368 // this->reset(this->get()) works. |
| 372 void reset(C* p = NULL) { | 369 void reset(C* p = NULL) { |
| 373 if (ptr_ != p) { | 370 if (ptr_ != p) { |
| 374 FreeProc free_proc; | 371 FreeProc free_proc; |
| 375 free_proc(ptr_); | 372 free_proc(ptr_); |
| 376 ptr_ = p; | 373 ptr_ = p; |
| 377 } | 374 } |
| 378 } | 375 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 // The return value is the current pointer held by this object. | 415 // The return value is the current pointer held by this object. |
| 419 // If this object holds a NULL pointer, the return value is NULL. | 416 // If this object holds a NULL pointer, the return value is NULL. |
| 420 // After this operation, this object will hold a NULL pointer, | 417 // After this operation, this object will hold a NULL pointer, |
| 421 // and will not own the object any more. | 418 // and will not own the object any more. |
| 422 C* release() WARN_UNUSED_RESULT { | 419 C* release() WARN_UNUSED_RESULT { |
| 423 C* tmp = ptr_; | 420 C* tmp = ptr_; |
| 424 ptr_ = NULL; | 421 ptr_ = NULL; |
| 425 return tmp; | 422 return tmp; |
| 426 } | 423 } |
| 427 | 424 |
| 428 CPP_03_MOVE_EMULATION(scoped_ptr_malloc, ptr_); | |
| 429 | |
| 430 private: | 425 private: |
| 431 C* ptr_; | 426 C* ptr_; |
| 432 | 427 |
| 433 // no reason to use these: each scoped_ptr_malloc should have its own object | 428 // no reason to use these: each scoped_ptr_malloc should have its own object |
| 434 template <class C2, class GP> | 429 template <class C2, class GP> |
| 435 bool operator==(scoped_ptr_malloc<C2, GP> const& p) const; | 430 bool operator==(scoped_ptr_malloc<C2, GP> const& p) const; |
| 436 template <class C2, class GP> | 431 template <class C2, class GP> |
| 437 bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const; | 432 bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const; |
| 438 | |
| 439 // Disallow evil constructors. Note that MUST NOT take a const& because we | |
| 440 // are implementing move semantics. See the CPP_03_MOVE_EMULATION macro. | |
| 441 scoped_ptr_malloc(scoped_ptr_malloc&); | |
| 442 void operator=(scoped_ptr_malloc&); | |
| 443 }; | 433 }; |
| 444 | 434 |
| 445 #undef CPP_03_MOVE_EMULATION | |
| 446 | |
| 447 template<class C, class FP> inline | 435 template<class C, class FP> inline |
| 448 void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) { | 436 void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) { |
| 449 a.swap(b); | 437 a.swap(b); |
| 450 } | 438 } |
| 451 | 439 |
| 452 template<class C, class FP> inline | 440 template<class C, class FP> inline |
| 453 bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) { | 441 bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) { |
| 454 return p == b.get(); | 442 return p == b.get(); |
| 455 } | 443 } |
| 456 | 444 |
| 457 template<class C, class FP> inline | 445 template<class C, class FP> inline |
| 458 bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) { | 446 bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) { |
| 459 return p != b.get(); | 447 return p != b.get(); |
| 460 } | 448 } |
| 461 | 449 |
| 462 #endif // BASE_MEMORY_SCOPED_PTR_H_ | 450 #endif // BASE_MEMORY_SCOPED_PTR_H_ |
| OLD | NEW |