Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 14 matching lines...) Expand all Loading... | |
| 25 // foo.reset(); // Foo("wee4") destroyed, foo no longer | 25 // foo.reset(); // Foo("wee4") destroyed, foo no longer |
| 26 // // manages a pointer. | 26 // // manages a pointer. |
| 27 // } // foo wasn't managing a pointer, so nothing was destroyed. | 27 // } // foo wasn't managing a pointer, so nothing was destroyed. |
| 28 // | 28 // |
| 29 // Example usage (scoped_array): | 29 // Example usage (scoped_array): |
| 30 // { | 30 // { |
| 31 // scoped_array<Foo> foo(new Foo[100]); | 31 // scoped_array<Foo> foo(new Foo[100]); |
| 32 // foo.get()->Method(); // Foo::Method on the 0th element. | 32 // foo.get()->Method(); // Foo::Method on the 0th element. |
| 33 // foo[10].Method(); // Foo::Method on the 10th element. | 33 // foo[10].Method(); // Foo::Method on the 10th element. |
| 34 // } | 34 // } |
| 35 // | |
| 36 // These scopers also implement part of the functionality of C++11 unique_ptr | |
| 37 // in that they are "moveable but not copyable." You can use the scopers in | |
| 38 // the parameter and return types of functions to signify ownership transfer | |
| 39 // in to and out of a function. When calling a function that has a scoper | |
| 40 // as the argument type, it must be called with the result of an analogous | |
| 41 // scoper's Pass() function or another funciton that generates a temporary; | |
| 42 // passing by copy will NOT work. Here is an example using scoped_ptr: | |
| 43 // | |
| 44 // void TakesOwnership(scoped_ptr<Foo> arg) { | |
| 45 // // Do something with arg | |
| 46 // } | |
| 47 // scoped_ptr<Foo> CreateFoo() { | |
| 48 // return scoped_ptr<Foo>(new Foo("new")); | |
| 49 // } | |
| 50 // scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) { | |
| 51 // return arg.Pass(); | |
| 52 // } | |
| 53 // | |
| 54 // { | |
| 55 // scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay)" | |
| 56 // TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay"). | |
| 57 // scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo. | |
| 58 // scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2. | |
| 59 // PassThru(ptr2.Pass()); // ptr2 is correspondly NULL. | |
| 60 // } | |
| 61 // | |
| 62 // Notice that if you do not call Pass() when retruning from CreateFoo(), or | |
|
darin (slow to review)
2011/12/03 00:25:10
retruning -> returning
awong
2011/12/06 00:02:08
Done.
| |
| 63 // when invoking TakesOwnership(), the code will not compile because scopers | |
| 64 // are not copyable; they only implement move semantics based on the Pass() | |
| 65 // function. | |
| 35 | 66 |
| 36 #ifndef BASE_MEMORY_SCOPED_PTR_H_ | 67 #ifndef BASE_MEMORY_SCOPED_PTR_H_ |
| 37 #define BASE_MEMORY_SCOPED_PTR_H_ | 68 #define BASE_MEMORY_SCOPED_PTR_H_ |
| 38 #pragma once | 69 #pragma once |
| 39 | 70 |
| 40 // This is an implementation designed to match the anticipated future TR2 | 71 // This is an implementation designed to match the anticipated future TR2 |
| 41 // implementation of the scoped_ptr class, and its closely-related brethren, | 72 // implementation of the scoped_ptr class, and its closely-related brethren, |
| 42 // scoped_array, scoped_ptr_malloc. | 73 // scoped_array, scoped_ptr_malloc. |
| 43 | 74 |
| 44 #include <assert.h> | 75 #include <assert.h> |
| 45 #include <stddef.h> | 76 #include <stddef.h> |
| 46 #include <stdlib.h> | 77 #include <stdlib.h> |
| 47 | 78 |
| 48 #include "base/compiler_specific.h" | 79 #include "base/compiler_specific.h" |
| 49 | 80 |
| 81 // Macro with the boilerplate C++03 move emulation for a class. | |
| 82 // | |
| 83 // In C++11, this is done via r-value references. Here, we use | |
| 84 // C++03 move emulation. For a more detailed explanation, see: | |
| 85 // | |
| 86 // http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor | |
| 87 // | |
| 88 #define CPP_03_MOVE_EMULATION(scoper, field) \ | |
| 89 private: \ | |
| 90 struct MoveProxy { \ | |
| 91 explicit MoveProxy(scoper& obj) : obj_(obj) {} \ | |
| 92 scoper& obj_; \ | |
| 93 }; \ | |
| 94 public: \ | |
| 95 operator MoveProxy() { return MoveProxy(*this); } \ | |
| 96 scoper(MoveProxy proxy) : field(proxy.obj_.release()) { } \ | |
| 97 scoper& operator=(MoveProxy proxy) { \ | |
| 98 swap(proxy.obj_); \ | |
| 99 return *this; \ | |
| 100 } \ | |
| 101 scoper Pass() { return scoper(MoveProxy(*this)); } | |
| 102 | |
| 50 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> | 103 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> |
| 51 // automatically deletes the pointer it holds (if any). | 104 // automatically deletes the pointer it holds (if any). |
| 52 // That is, scoped_ptr<T> owns the T object that it points to. | 105 // That is, scoped_ptr<T> owns the T object that it points to. |
| 53 // Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. | 106 // Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. |
| 54 // Also like T*, scoped_ptr<T> is thread-compatible, and once you | 107 // Also like T*, scoped_ptr<T> is thread-compatible, and once you |
| 55 // dereference it, you get the threadsafety guarantees of T. | 108 // dereference it, you get the threadsafety guarantees of T. |
| 56 // | 109 // |
| 57 // The size of a scoped_ptr is small: | 110 // The size of a scoped_ptr is small: |
| 58 // sizeof(scoped_ptr<C>) == sizeof(C*) | 111 // sizeof(scoped_ptr<C>) == sizeof(C*) |
| 59 template <class C> | 112 template <class C> |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 115 // The return value is the current pointer held by this object. | 168 // The return value is the current pointer held by this object. |
| 116 // If this object holds a NULL pointer, the return value is NULL. | 169 // If this object holds a NULL pointer, the return value is NULL. |
| 117 // After this operation, this object will hold a NULL pointer, | 170 // After this operation, this object will hold a NULL pointer, |
| 118 // and will not own the object any more. | 171 // and will not own the object any more. |
| 119 C* release() WARN_UNUSED_RESULT { | 172 C* release() WARN_UNUSED_RESULT { |
| 120 C* retVal = ptr_; | 173 C* retVal = ptr_; |
| 121 ptr_ = NULL; | 174 ptr_ = NULL; |
| 122 return retVal; | 175 return retVal; |
| 123 } | 176 } |
| 124 | 177 |
| 178 CPP_03_MOVE_EMULATION(scoped_ptr, ptr_); | |
| 179 | |
| 125 private: | 180 private: |
| 126 C* ptr_; | 181 C* ptr_; |
| 127 | 182 |
| 128 // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't | 183 // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't |
| 129 // make sense, and if C2 == C, it still doesn't make sense because you should | 184 // make sense, and if C2 == C, it still doesn't make sense because you should |
| 130 // never have the same object owned by two different scoped_ptrs. | 185 // never have the same object owned by two different scoped_ptrs. |
| 131 template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; | 186 template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; |
| 132 template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; | 187 template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; |
| 133 | 188 |
| 134 // Disallow evil constructors | 189 // Disallow evil constructors. Note that MUST NOT take a const& because we |
| 135 scoped_ptr(const scoped_ptr&); | 190 // are implmenting move semantics. See the CPP_03_MOVE_EMULATION macro. |
| 136 void operator=(const scoped_ptr&); | 191 scoped_ptr(scoped_ptr&); |
| 192 void operator=(scoped_ptr&); | |
| 137 }; | 193 }; |
| 138 | 194 |
| 139 // Free functions | 195 // Free functions |
| 140 template <class C> | 196 template <class C> |
| 141 void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) { | 197 void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) { |
| 142 p1.swap(p2); | 198 p1.swap(p2); |
| 143 } | 199 } |
| 144 | 200 |
| 145 template <class C> | 201 template <class C> |
| 146 bool operator==(C* p1, const scoped_ptr<C>& p2) { | 202 bool operator==(C* p1, const scoped_ptr<C>& p2) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 222 // The return value is the current pointer held by this object. | 278 // The return value is the current pointer held by this object. |
| 223 // If this object holds a NULL pointer, the return value is NULL. | 279 // If this object holds a NULL pointer, the return value is NULL. |
| 224 // After this operation, this object will hold a NULL pointer, | 280 // After this operation, this object will hold a NULL pointer, |
| 225 // and will not own the object any more. | 281 // and will not own the object any more. |
| 226 C* release() WARN_UNUSED_RESULT { | 282 C* release() WARN_UNUSED_RESULT { |
| 227 C* retVal = array_; | 283 C* retVal = array_; |
| 228 array_ = NULL; | 284 array_ = NULL; |
| 229 return retVal; | 285 return retVal; |
| 230 } | 286 } |
| 231 | 287 |
| 288 CPP_03_MOVE_EMULATION(scoped_array, array_); | |
| 289 | |
| 232 private: | 290 private: |
| 233 C* array_; | 291 C* array_; |
| 234 | 292 |
| 235 // Forbid comparison of different scoped_array types. | 293 // Forbid comparison of different scoped_array types. |
| 236 template <class C2> bool operator==(scoped_array<C2> const& p2) const; | 294 template <class C2> bool operator==(scoped_array<C2> const& p2) const; |
| 237 template <class C2> bool operator!=(scoped_array<C2> const& p2) const; | 295 template <class C2> bool operator!=(scoped_array<C2> const& p2) const; |
| 238 | 296 |
| 239 // Disallow evil constructors | 297 // Disallow evil constructors. Note that MUST NOT take a const& because we |
| 240 scoped_array(const scoped_array&); | 298 // are implmenting move semantics. See the CPP_03_MOVE_EMULATION macro. |
| 241 void operator=(const scoped_array&); | 299 scoped_array(scoped_array&); |
| 300 void operator=(scoped_array&); | |
| 242 }; | 301 }; |
| 243 | 302 |
| 244 // Free functions | 303 // Free functions |
| 245 template <class C> | 304 template <class C> |
| 246 void swap(scoped_array<C>& p1, scoped_array<C>& p2) { | 305 void swap(scoped_array<C>& p1, scoped_array<C>& p2) { |
| 247 p1.swap(p2); | 306 p1.swap(p2); |
| 248 } | 307 } |
| 249 | 308 |
| 250 template <class C> | 309 template <class C> |
| 251 bool operator==(C* p1, const scoped_array<C>& p2) { | 310 bool operator==(C* p1, const scoped_array<C>& p2) { |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 340 // The return value is the current pointer held by this object. | 399 // The return value is the current pointer held by this object. |
| 341 // If this object holds a NULL pointer, the return value is NULL. | 400 // If this object holds a NULL pointer, the return value is NULL. |
| 342 // After this operation, this object will hold a NULL pointer, | 401 // After this operation, this object will hold a NULL pointer, |
| 343 // and will not own the object any more. | 402 // and will not own the object any more. |
| 344 C* release() WARN_UNUSED_RESULT { | 403 C* release() WARN_UNUSED_RESULT { |
| 345 C* tmp = ptr_; | 404 C* tmp = ptr_; |
| 346 ptr_ = NULL; | 405 ptr_ = NULL; |
| 347 return tmp; | 406 return tmp; |
| 348 } | 407 } |
| 349 | 408 |
| 409 CPP_03_MOVE_EMULATION(scoped_ptr_malloc, ptr_); | |
| 410 | |
| 350 private: | 411 private: |
| 351 C* ptr_; | 412 C* ptr_; |
| 352 | 413 |
| 353 // no reason to use these: each scoped_ptr_malloc should have its own object | 414 // no reason to use these: each scoped_ptr_malloc should have its own object |
| 354 template <class C2, class GP> | 415 template <class C2, class GP> |
| 355 bool operator==(scoped_ptr_malloc<C2, GP> const& p) const; | 416 bool operator==(scoped_ptr_malloc<C2, GP> const& p) const; |
| 356 template <class C2, class GP> | 417 template <class C2, class GP> |
| 357 bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const; | 418 bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const; |
| 358 | 419 |
| 359 // Disallow evil constructors | 420 // Disallow evil constructors. Note that MUST NOT take a const& because we |
| 360 scoped_ptr_malloc(const scoped_ptr_malloc&); | 421 // are implmenting move semantics. See the CPP_03_MOVE_EMULATION macro. |
| 361 void operator=(const scoped_ptr_malloc&); | 422 scoped_ptr_malloc(scoped_ptr_malloc&); |
| 423 void operator=(scoped_ptr_malloc&); | |
| 362 }; | 424 }; |
| 363 | 425 |
| 426 #undef CPP_03_MOVE_EMULATION | |
| 427 | |
| 364 template<class C, class FP> inline | 428 template<class C, class FP> inline |
| 365 void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) { | 429 void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) { |
| 366 a.swap(b); | 430 a.swap(b); |
| 367 } | 431 } |
| 368 | 432 |
| 369 template<class C, class FP> inline | 433 template<class C, class FP> inline |
| 370 bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) { | 434 bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) { |
| 371 return p == b.get(); | 435 return p == b.get(); |
| 372 } | 436 } |
| 373 | 437 |
| 374 template<class C, class FP> inline | 438 template<class C, class FP> inline |
| 375 bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) { | 439 bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) { |
| 376 return p != b.get(); | 440 return p != b.get(); |
| 377 } | 441 } |
| 378 | 442 |
| 379 #endif // BASE_MEMORY_SCOPED_PTR_H_ | 443 #endif // BASE_MEMORY_SCOPED_PTR_H_ |
| OLD | NEW |