Chromium Code Reviews| 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 a | 5 // Scopers help you manage ownership of a pointer, helping you easily manage a |
| 6 // pointer within a scope, and automatically destroying the pointer at the end | 6 // pointer within a scope, and automatically destroying the pointer at the end |
| 7 // of a scope. There are two main classes you will use, which correspond to the | 7 // of a scope. There are two main classes you will use, which correspond to the |
| 8 // operators new/delete and new[]/delete[]. | 8 // operators new/delete and new[]/delete[]. |
| 9 // | 9 // |
| 10 // Example usage (scoped_ptr<T>): | 10 // Example usage (scoped_ptr<T>): |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 | 79 |
| 80 // This is an implementation designed to match the anticipated future TR2 | 80 // This is an implementation designed to match the anticipated future TR2 |
| 81 // implementation of the scoped_ptr class. | 81 // implementation of the scoped_ptr class. |
| 82 | 82 |
| 83 #include <assert.h> | 83 #include <assert.h> |
| 84 #include <stddef.h> | 84 #include <stddef.h> |
| 85 #include <stdlib.h> | 85 #include <stdlib.h> |
| 86 | 86 |
| 87 #include <algorithm> // For std::swap(). | 87 #include <algorithm> // For std::swap(). |
| 88 #include <iosfwd> | 88 #include <iosfwd> |
| 89 #include <memory> | |
| 90 #include <utility> | |
| 89 | 91 |
| 90 #include "base/basictypes.h" | 92 #include "base/basictypes.h" |
| 91 #include "base/compiler_specific.h" | 93 #include "base/compiler_specific.h" |
| 92 #include "base/move.h" | 94 #include "base/move.h" |
| 93 #include "base/template_util.h" | 95 #include "base/template_util.h" |
| 94 | 96 |
| 95 namespace base { | 97 namespace base { |
| 96 | 98 |
| 97 namespace subtle { | 99 namespace subtle { |
| 98 class RefCountedBase; | 100 class RefCountedBase; |
| 99 class RefCountedThreadSafeBase; | 101 class RefCountedThreadSafeBase; |
| 100 } // namespace subtle | 102 } // namespace subtle |
| 101 | 103 |
| 102 // Function object which deletes its parameter, which must be a pointer. | |
| 103 // If C is an array type, invokes 'delete[]' on the parameter; otherwise, | |
| 104 // invokes 'delete'. The default deleter for scoped_ptr<T>. | |
| 105 template <class T> | |
| 106 struct DefaultDeleter { | |
|
dcheng
2015/11/11 16:18:34
I tried using a type alias, but apparently the sta
| |
| 107 DefaultDeleter() {} | |
| 108 template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) { | |
| 109 // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor | |
| 110 // if U* is implicitly convertible to T* and U is not an array type. | |
| 111 // | |
| 112 // Correct implementation should use SFINAE to disable this | |
| 113 // constructor. However, since there are no other 1-argument constructors, | |
| 114 // using a COMPILE_ASSERT() based on is_convertible<> and requiring | |
| 115 // complete types is simpler and will cause compile failures for equivalent | |
| 116 // misuses. | |
| 117 // | |
| 118 // Note, the is_convertible<U*, T*> check also ensures that U is not an | |
| 119 // array. T is guaranteed to be a non-array, so any U* where U is an array | |
| 120 // cannot convert to T*. | |
| 121 enum { T_must_be_complete = sizeof(T) }; | |
| 122 enum { U_must_be_complete = sizeof(U) }; | |
| 123 COMPILE_ASSERT((base::is_convertible<U*, T*>::value), | |
| 124 U_ptr_must_implicitly_convert_to_T_ptr); | |
| 125 } | |
| 126 inline void operator()(T* ptr) const { | |
| 127 enum { type_must_be_complete = sizeof(T) }; | |
| 128 delete ptr; | |
| 129 } | |
| 130 }; | |
| 131 | |
| 132 // Specialization of DefaultDeleter for array types. | |
| 133 template <class T> | |
| 134 struct DefaultDeleter<T[]> { | |
| 135 inline void operator()(T* ptr) const { | |
| 136 enum { type_must_be_complete = sizeof(T) }; | |
| 137 delete[] ptr; | |
| 138 } | |
| 139 | |
| 140 private: | |
| 141 // Disable this operator for any U != T because it is undefined to execute | |
| 142 // an array delete when the static type of the array mismatches the dynamic | |
| 143 // type. | |
| 144 // | |
| 145 // References: | |
| 146 // C++98 [expr.delete]p3 | |
| 147 // http://cplusplus.github.com/LWG/lwg-defects.html#938 | |
| 148 template <typename U> void operator()(U* array) const; | |
| 149 }; | |
| 150 | |
| 151 template <class T, int n> | |
| 152 struct DefaultDeleter<T[n]> { | |
| 153 // Never allow someone to declare something like scoped_ptr<int[10]>. | |
| 154 COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type); | |
| 155 }; | |
| 156 | |
| 157 // Function object which invokes 'free' on its parameter, which must be | 104 // Function object which invokes 'free' on its parameter, which must be |
| 158 // a pointer. Can be used to store malloc-allocated pointers in scoped_ptr: | 105 // a pointer. Can be used to store malloc-allocated pointers in scoped_ptr: |
| 159 // | 106 // |
| 160 // scoped_ptr<int, base::FreeDeleter> foo_ptr( | 107 // scoped_ptr<int, base::FreeDeleter> foo_ptr( |
| 161 // static_cast<int*>(malloc(sizeof(int)))); | 108 // static_cast<int*>(malloc(sizeof(int)))); |
| 162 struct FreeDeleter { | 109 struct FreeDeleter { |
| 163 inline void operator()(void* ptr) const { | 110 inline void operator()(void* ptr) const { |
| 164 free(ptr); | 111 free(ptr); |
| 165 } | 112 } |
| 166 }; | 113 }; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 template <typename U, typename V> | 148 template <typename U, typename V> |
| 202 scoped_ptr_impl(scoped_ptr_impl<U, V>* other) | 149 scoped_ptr_impl(scoped_ptr_impl<U, V>* other) |
| 203 : data_(other->release(), other->get_deleter()) { | 150 : data_(other->release(), other->get_deleter()) { |
| 204 // We do not support move-only deleters. We could modify our move | 151 // We do not support move-only deleters. We could modify our move |
| 205 // emulation to have base::subtle::move() and base::subtle::forward() | 152 // emulation to have base::subtle::move() and base::subtle::forward() |
| 206 // functions that are imperfect emulations of their C++11 equivalents, | 153 // functions that are imperfect emulations of their C++11 equivalents, |
| 207 // but until there's a requirement, just assume deleters are copyable. | 154 // but until there's a requirement, just assume deleters are copyable. |
| 208 } | 155 } |
| 209 | 156 |
| 210 template <typename U, typename V> | 157 template <typename U, typename V> |
| 158 void TakeState(std::unique_ptr<U, V>* other) { | |
| 159 reset(other->release()); | |
| 160 get_deleter() = other->get_deleter(); | |
| 161 } | |
| 162 | |
| 163 template <typename U, typename V> | |
| 211 void TakeState(scoped_ptr_impl<U, V>* other) { | 164 void TakeState(scoped_ptr_impl<U, V>* other) { |
| 212 // See comment in templated constructor above regarding lack of support | 165 // See comment in templated constructor above regarding lack of support |
| 213 // for move-only deleters. | 166 // for move-only deleters. |
| 214 reset(other->release()); | 167 reset(other->release()); |
| 215 get_deleter() = other->get_deleter(); | 168 get_deleter() = other->get_deleter(); |
| 216 } | 169 } |
| 217 | 170 |
| 218 ~scoped_ptr_impl() { | 171 ~scoped_ptr_impl() { |
| 219 // Match libc++, which calls reset() in its destructor. | 172 // Match libc++, which calls reset() in its destructor. |
| 220 // Use nullptr as the new value for three reasons: | 173 // Use nullptr as the new value for three reasons: |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 // | 249 // |
| 297 // The size of scoped_ptr is small. On most compilers, when using the | 250 // The size of scoped_ptr is small. On most compilers, when using the |
| 298 // DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will | 251 // DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will |
| 299 // increase the size proportional to whatever state they need to have. See | 252 // increase the size proportional to whatever state they need to have. See |
| 300 // comments inside scoped_ptr_impl<> for details. | 253 // comments inside scoped_ptr_impl<> for details. |
| 301 // | 254 // |
| 302 // Current implementation targets having a strict subset of C++11's | 255 // Current implementation targets having a strict subset of C++11's |
| 303 // unique_ptr<> features. Known deficiencies include not supporting move-only | 256 // unique_ptr<> features. Known deficiencies include not supporting move-only |
| 304 // deleteres, function pointers as deleters, and deleters with reference | 257 // deleteres, function pointers as deleters, and deleters with reference |
| 305 // types. | 258 // types. |
| 306 template <class T, class D = base::DefaultDeleter<T> > | 259 template <class T, class D = std::default_delete<T>> |
| 307 class scoped_ptr { | 260 class scoped_ptr { |
| 308 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) | 261 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) |
| 309 | 262 |
| 310 COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value, | 263 COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value, |
| 311 T_is_refcounted_type_and_needs_scoped_refptr); | 264 T_is_refcounted_type_and_needs_scoped_refptr); |
| 312 | 265 |
| 313 public: | 266 public: |
| 314 // The element and deleter types. | 267 // The element and deleter types. |
| 315 typedef T element_type; | 268 typedef T element_type; |
| 316 typedef D deleter_type; | 269 typedef D deleter_type; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 415 } | 368 } |
| 416 | 369 |
| 417 // Release a pointer. | 370 // Release a pointer. |
| 418 // The return value is the current pointer held by this object. If this object | 371 // The return value is the current pointer held by this object. If this object |
| 419 // holds a nullptr, the return value is nullptr. After this operation, this | 372 // holds a nullptr, the return value is nullptr. After this operation, this |
| 420 // object will hold a nullptr, and will not own the object any more. | 373 // object will hold a nullptr, and will not own the object any more. |
| 421 element_type* release() WARN_UNUSED_RESULT { | 374 element_type* release() WARN_UNUSED_RESULT { |
| 422 return impl_.release(); | 375 return impl_.release(); |
| 423 } | 376 } |
| 424 | 377 |
| 378 // Conversion shims to help with the std::unique_ptr transition. | |
| 379 template <typename U, typename V> | |
| 380 scoped_ptr(std::unique_ptr<U, V>&& p) | |
| 381 : impl_(p.release(), p.get_deleter()) {} | |
| 382 | |
| 383 template <typename U, typename V> | |
| 384 scoped_ptr& operator=(std::unique_ptr<U, V>&& p) { | |
| 385 impl_.TakeState(&p); | |
| 386 return *this; | |
| 387 } | |
| 388 | |
| 389 template <typename U, typename V> | |
| 390 operator std::unique_ptr<U, V>() && { | |
|
danakj
2015/11/14 01:29:31
Vlad pointed out that this doesn't work yet in MSV
dcheng
2015/11/14 01:37:10
Argh. That's obnoxious. Having asymmetrical ways t
| |
| 391 return std::unique_ptr<U, V>(release(), get_deleter()); | |
| 392 } | |
| 393 | |
| 425 private: | 394 private: |
| 426 // Needed to reach into |impl_| in the constructor. | 395 // Needed to reach into |impl_| in the constructor. |
| 427 template <typename U, typename V> friend class scoped_ptr; | 396 template <typename U, typename V> friend class scoped_ptr; |
| 428 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; | 397 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; |
| 429 | 398 |
| 430 // Forbidden for API compatibility with std::unique_ptr. | 399 // Forbidden for API compatibility with std::unique_ptr. |
| 431 explicit scoped_ptr(int disallow_construction_from_null); | 400 explicit scoped_ptr(int disallow_construction_from_null); |
| 432 | 401 |
| 433 // Forbid comparison of scoped_ptr types. If U != T, it totally | 402 // Forbid comparison of scoped_ptr types. If U != T, it totally |
| 434 // doesn't make sense, and if U == T, it still doesn't make sense | 403 // doesn't make sense, and if U == T, it still doesn't make sense |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 520 } | 489 } |
| 521 | 490 |
| 522 // Release a pointer. | 491 // Release a pointer. |
| 523 // The return value is the current pointer held by this object. If this object | 492 // The return value is the current pointer held by this object. If this object |
| 524 // holds a nullptr, the return value is nullptr. After this operation, this | 493 // holds a nullptr, the return value is nullptr. After this operation, this |
| 525 // object will hold a nullptr, and will not own the object any more. | 494 // object will hold a nullptr, and will not own the object any more. |
| 526 element_type* release() WARN_UNUSED_RESULT { | 495 element_type* release() WARN_UNUSED_RESULT { |
| 527 return impl_.release(); | 496 return impl_.release(); |
| 528 } | 497 } |
| 529 | 498 |
| 499 // Conversion shims to help with the std::unique_ptr transition. | |
| 500 scoped_ptr(std::unique_ptr<T[], D>&& p) | |
|
dcheng
2015/11/11 16:18:34
To keep things simple, the T[] specializations jus
danakj
2015/11/14 01:29:31
Can you put that in the comment?
| |
| 501 : impl_(p.release(), p.get_deleter()) {} | |
| 502 | |
| 503 scoped_ptr& operator=(std::unique_ptr<T[], D>&& p) { | |
| 504 impl_.TakeState(&p); | |
| 505 return *this; | |
| 506 } | |
| 507 | |
| 508 operator std::unique_ptr<T[], D>() && { | |
|
danakj
2015/11/14 01:29:31
explain the && here too
danakj
2015/11/14 01:30:06
oops, nevermind this one.
| |
| 509 return std::unique_ptr<T[], D>(release(), get_deleter()); | |
| 510 } | |
| 511 | |
| 530 private: | 512 private: |
| 531 // Force element_type to be a complete type. | 513 // Force element_type to be a complete type. |
| 532 enum { type_must_be_complete = sizeof(element_type) }; | 514 enum { type_must_be_complete = sizeof(element_type) }; |
| 533 | 515 |
| 534 // Actually hold the data. | 516 // Actually hold the data. |
| 535 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; | 517 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; |
| 536 | 518 |
| 537 // Disable initialization from any type other than element_type*, by | 519 // Disable initialization from any type other than element_type*, by |
| 538 // providing a constructor that matches such an initialization, but is | 520 // providing a constructor that matches such an initialization, but is |
| 539 // private and has no definition. This is disabled because it is not safe to | 521 // private and has no definition. This is disabled because it is not safe to |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 578 scoped_ptr<T> make_scoped_ptr(T* ptr) { | 560 scoped_ptr<T> make_scoped_ptr(T* ptr) { |
| 579 return scoped_ptr<T>(ptr); | 561 return scoped_ptr<T>(ptr); |
| 580 } | 562 } |
| 581 | 563 |
| 582 template <typename T> | 564 template <typename T> |
| 583 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) { | 565 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) { |
| 584 return out << p.get(); | 566 return out << p.get(); |
| 585 } | 567 } |
| 586 | 568 |
| 587 #endif // BASE_MEMORY_SCOPED_PTR_H_ | 569 #endif // BASE_MEMORY_SCOPED_PTR_H_ |
| OLD | NEW |