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 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 #include <stddef.h> | 94 #include <stddef.h> |
95 #include <stdlib.h> | 95 #include <stdlib.h> |
96 | 96 |
97 #include <algorithm> // For std::swap(). | 97 #include <algorithm> // For std::swap(). |
98 | 98 |
99 #include "base/basictypes.h" | 99 #include "base/basictypes.h" |
100 #include "base/compiler_specific.h" | 100 #include "base/compiler_specific.h" |
101 #include "base/move.h" | 101 #include "base/move.h" |
102 #include "base/template_util.h" | 102 #include "base/template_util.h" |
103 | 103 |
| 104 #if defined(OS_POSIX) |
| 105 #include <unistd.h> // For _exit() on POSIX |
| 106 #endif |
| 107 |
104 namespace base { | 108 namespace base { |
105 | 109 |
106 namespace subtle { | 110 namespace subtle { |
107 class RefCountedBase; | 111 class RefCountedBase; |
108 class RefCountedThreadSafeBase; | 112 class RefCountedThreadSafeBase; |
109 } // namespace subtle | 113 } // namespace subtle |
110 | 114 |
111 // Function object which deletes its parameter, which must be a pointer. | 115 // Function object which deletes its parameter, which must be a pointer. |
112 // If C is an array type, invokes 'delete[]' on the parameter; otherwise, | 116 // If C is an array type, invokes 'delete[]' on the parameter; otherwise, |
113 // invokes 'delete'. The default deleter for scoped_ptr<T>. | 117 // invokes 'delete'. The default deleter for scoped_ptr<T>. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 namespace internal { | 181 namespace internal { |
178 | 182 |
179 template <typename T> struct IsNotRefCounted { | 183 template <typename T> struct IsNotRefCounted { |
180 enum { | 184 enum { |
181 value = !base::is_convertible<T*, base::subtle::RefCountedBase*>::value && | 185 value = !base::is_convertible<T*, base::subtle::RefCountedBase*>::value && |
182 !base::is_convertible<T*, base::subtle::RefCountedThreadSafeBase*>:: | 186 !base::is_convertible<T*, base::subtle::RefCountedThreadSafeBase*>:: |
183 value | 187 value |
184 }; | 188 }; |
185 }; | 189 }; |
186 | 190 |
| 191 template <typename T> |
| 192 struct ShouldAbortOnSelfReset { |
| 193 template <typename U> |
| 194 static NoType Test(const typename U::AllowSelfReset*); |
| 195 |
| 196 template <typename U> |
| 197 static YesType Test(...); |
| 198 |
| 199 static const bool value = sizeof(Test<T>(0)) == sizeof(YesType); |
| 200 }; |
| 201 |
187 // Minimal implementation of the core logic of scoped_ptr, suitable for | 202 // Minimal implementation of the core logic of scoped_ptr, suitable for |
188 // reuse in both scoped_ptr and its specializations. | 203 // reuse in both scoped_ptr and its specializations. |
189 template <class T, class D> | 204 template <class T, class D> |
190 class scoped_ptr_impl { | 205 class scoped_ptr_impl { |
191 public: | 206 public: |
192 explicit scoped_ptr_impl(T* p) : data_(p) {} | 207 explicit scoped_ptr_impl(T* p) : data_(p) {} |
193 | 208 |
194 // Initializer for deleters that have data parameters. | 209 // Initializer for deleters that have data parameters. |
195 scoped_ptr_impl(T* p, const D& d) : data_(p, d) {} | 210 scoped_ptr_impl(T* p, const D& d) : data_(p, d) {} |
196 | 211 |
(...skipping 18 matching lines...) Expand all Loading... |
215 | 230 |
216 ~scoped_ptr_impl() { | 231 ~scoped_ptr_impl() { |
217 if (data_.ptr != nullptr) { | 232 if (data_.ptr != nullptr) { |
218 // Not using get_deleter() saves one function call in non-optimized | 233 // Not using get_deleter() saves one function call in non-optimized |
219 // builds. | 234 // builds. |
220 static_cast<D&>(data_)(data_.ptr); | 235 static_cast<D&>(data_)(data_.ptr); |
221 } | 236 } |
222 } | 237 } |
223 | 238 |
224 void reset(T* p) { | 239 void reset(T* p) { |
225 // This is a self-reset, which is no longer allowed: http://crbug.com/162971 | 240 // This is a self-reset, which is no longer allowed for default deleters: |
226 if (p != nullptr && p == data_.ptr) | 241 // https://crbug.com/162971 |
227 abort(); | 242 if (ShouldAbortOnSelfReset<D>::value && p != nullptr && p == data_.ptr) |
| 243 _exit(1); |
228 | 244 |
229 // Note that running data_.ptr = p can lead to undefined behavior if | 245 // Note that running data_.ptr = p can lead to undefined behavior if |
230 // get_deleter()(get()) deletes this. In order to prevent this, reset() | 246 // get_deleter()(get()) deletes this. In order to prevent this, reset() |
231 // should update the stored pointer before deleting its old value. | 247 // should update the stored pointer before deleting its old value. |
232 // | 248 // |
233 // However, changing reset() to use that behavior may cause current code to | 249 // However, changing reset() to use that behavior may cause current code to |
234 // break in unexpected ways. If the destruction of the owned object | 250 // break in unexpected ways. If the destruction of the owned object |
235 // dereferences the scoped_ptr when it is destroyed by a call to reset(), | 251 // dereferences the scoped_ptr when it is destroyed by a call to reset(), |
236 // then it will incorrectly dispatch calls to |p| rather than the original | 252 // then it will incorrectly dispatch calls to |p| rather than the original |
237 // value of |data_.ptr|. | 253 // value of |data_.ptr|. |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
601 | 617 |
602 // A function to convert T* into scoped_ptr<T> | 618 // A function to convert T* into scoped_ptr<T> |
603 // Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation | 619 // Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation |
604 // for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg)) | 620 // for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg)) |
605 template <typename T> | 621 template <typename T> |
606 scoped_ptr<T> make_scoped_ptr(T* ptr) { | 622 scoped_ptr<T> make_scoped_ptr(T* ptr) { |
607 return scoped_ptr<T>(ptr); | 623 return scoped_ptr<T>(ptr); |
608 } | 624 } |
609 | 625 |
610 #endif // BASE_MEMORY_SCOPED_PTR_H_ | 626 #endif // BASE_MEMORY_SCOPED_PTR_H_ |
OLD | NEW |