Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(147)

Side by Side Diff: base/memory/scoped_ptr.h

Issue 1445003002: Use std::default_delete as the default deleter for scoped_ptr. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix Windows Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 #ifndef BASE_MEMORY_SCOPED_PTR_H_ 77 #ifndef BASE_MEMORY_SCOPED_PTR_H_
78 #define BASE_MEMORY_SCOPED_PTR_H_ 78 #define BASE_MEMORY_SCOPED_PTR_H_
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().
88 #include <iosfwd> 87 #include <iosfwd>
88 #include <memory>
89 #include <utility>
dcheng 2015/11/16 18:22:59 In line with bratell@'s proposal to #include <util
89 90
90 #include "base/basictypes.h" 91 #include "base/basictypes.h"
91 #include "base/compiler_specific.h" 92 #include "base/compiler_specific.h"
92 #include "base/move.h" 93 #include "base/move.h"
93 #include "base/template_util.h" 94 #include "base/template_util.h"
94 95
95 namespace base { 96 namespace base {
96 97
97 namespace subtle { 98 namespace subtle {
98 class RefCountedBase; 99 class RefCountedBase;
99 class RefCountedThreadSafeBase; 100 class RefCountedThreadSafeBase;
100 } // namespace subtle 101 } // namespace subtle
101 102
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 {
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]>.
danakj 2015/11/16 22:19:02 Is this check provided by libc++ somewhere? Should
dcheng 2015/11/17 17:08:42 It's not explicitly provided by libc++. For exampl
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 103 // 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: 104 // a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
159 // 105 //
160 // scoped_ptr<int, base::FreeDeleter> foo_ptr( 106 // scoped_ptr<int, base::FreeDeleter> foo_ptr(
161 // static_cast<int*>(malloc(sizeof(int)))); 107 // static_cast<int*>(malloc(sizeof(int))));
162 struct FreeDeleter { 108 struct FreeDeleter {
163 inline void operator()(void* ptr) const { 109 inline void operator()(void* ptr) const {
164 free(ptr); 110 free(ptr);
165 } 111 }
166 }; 112 };
167 113
168 namespace internal { 114 namespace internal {
169 115
170 template <typename T> struct IsNotRefCounted { 116 template <typename T> struct IsNotRefCounted {
171 enum { 117 enum {
172 value = !base::is_convertible<T*, base::subtle::RefCountedBase*>::value && 118 value = !base::is_convertible<T*, base::subtle::RefCountedBase*>::value &&
173 !base::is_convertible<T*, base::subtle::RefCountedThreadSafeBase*>:: 119 !base::is_convertible<T*, base::subtle::RefCountedThreadSafeBase*>::
174 value 120 value
175 }; 121 };
176 }; 122 };
177 123
178 template <typename T> 124 template <typename T>
179 struct ShouldAbortOnSelfReset { 125 struct ShouldAbortOnSelfReset {
danakj 2015/11/16 22:19:02 Does this go away then?
dcheng 2015/11/17 17:08:42 Yes, it should.
180 template <typename U> 126 template <typename U>
181 static NoType Test(const typename U::AllowSelfReset*); 127 static NoType Test(const typename U::AllowSelfReset*);
danakj 2015/11/16 22:19:02 And any instances of AllowSelfReset in the codebas
dcheng 2015/11/17 17:08:42 Good catch, I forgot that there's some code in //n
182 128
183 template <typename U> 129 template <typename U>
184 static YesType Test(...); 130 static YesType Test(...);
185 131
186 static const bool value = sizeof(Test<T>(0)) == sizeof(YesType); 132 static const bool value = sizeof(Test<T>(0)) == sizeof(YesType);
187 }; 133 };
188 134
189 // Minimal implementation of the core logic of scoped_ptr, suitable for 135 // Minimal implementation of the core logic of scoped_ptr, suitable for
190 // reuse in both scoped_ptr and its specializations. 136 // reuse in both scoped_ptr and its specializations.
191 template <class T, class D> 137 template <class T, class D>
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 // in a reference cycle (see ScopedPtrTest.ReferenceCycle). 169 // in a reference cycle (see ScopedPtrTest.ReferenceCycle).
224 // 3. If |this| is accessed in the future, in a use-after-free bug, attempts 170 // 3. If |this| is accessed in the future, in a use-after-free bug, attempts
225 // to dereference |this|'s pointer should cause either a failure or a 171 // to dereference |this|'s pointer should cause either a failure or a
226 // segfault closer to the problem. If |this| wasn't reset to nullptr, 172 // segfault closer to the problem. If |this| wasn't reset to nullptr,
227 // the access would cause the deleted memory to be read or written 173 // the access would cause the deleted memory to be read or written
228 // leading to other more subtle issues. 174 // leading to other more subtle issues.
229 reset(nullptr); 175 reset(nullptr);
230 } 176 }
231 177
232 void reset(T* p) { 178 void reset(T* p) {
233 // This is a self-reset, which is no longer allowed for default deleters:
234 // https://crbug.com/162971
235 assert(!ShouldAbortOnSelfReset<D>::value || p == nullptr || p != data_.ptr);
danakj 2015/11/16 22:19:02 I'm not sure why this went away in this CL TBH. I
dcheng 2015/11/17 17:08:42 This is just making the interface match std::uniqu
danakj 2015/11/17 19:09:27 Yah, I kinda figured this would make a reasonable
236
237 // Match C++11's definition of unique_ptr::reset(), which requires changing 179 // Match C++11's definition of unique_ptr::reset(), which requires changing
238 // the pointer before invoking the deleter on the old pointer. This prevents 180 // the pointer before invoking the deleter on the old pointer. This prevents
239 // |this| from being accessed after the deleter is run, which may destroy 181 // |this| from being accessed after the deleter is run, which may destroy
240 // |this|. 182 // |this|.
241 T* old = data_.ptr; 183 T* old = data_.ptr;
242 data_.ptr = p; 184 data_.ptr = p;
243 if (old != nullptr) 185 if (old != nullptr)
244 static_cast<D&>(data_)(old); 186 static_cast<D&>(data_)(old);
245 } 187 }
246 188
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 } // namespace base 230 } // namespace base
289 231
290 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> 232 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
291 // automatically deletes the pointer it holds (if any). 233 // automatically deletes the pointer it holds (if any).
292 // That is, scoped_ptr<T> owns the T object that it points to. 234 // That is, scoped_ptr<T> owns the T object that it points to.
293 // Like a T*, a scoped_ptr<T> may hold either nullptr or a pointer to a T 235 // Like a T*, a scoped_ptr<T> may hold either nullptr or a pointer to a T
294 // object. Also like T*, scoped_ptr<T> is thread-compatible, and once you 236 // object. Also like T*, scoped_ptr<T> is thread-compatible, and once you
295 // dereference it, you get the thread safety guarantees of T. 237 // dereference it, you get the thread safety guarantees of T.
296 // 238 //
297 // The size of scoped_ptr is small. On most compilers, when using the 239 // The size of scoped_ptr is small. On most compilers, when using the
298 // DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will 240 // std::default_delete, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters
299 // increase the size proportional to whatever state they need to have. See 241 // will increase the size proportional to whatever state they need to have. See
300 // comments inside scoped_ptr_impl<> for details. 242 // comments inside scoped_ptr_impl<> for details.
301 // 243 //
302 // Current implementation targets having a strict subset of C++11's 244 // Current implementation targets having a strict subset of C++11's
303 // unique_ptr<> features. Known deficiencies include not supporting move-only 245 // unique_ptr<> features. Known deficiencies include not supporting move-only
304 // deleteres, function pointers as deleters, and deleters with reference 246 // deleteres, function pointers as deleters, and deleters with reference
305 // types. 247 // types.
306 template <class T, class D = base::DefaultDeleter<T> > 248 template <class T, class D = std::default_delete<T>>
307 class scoped_ptr { 249 class scoped_ptr {
308 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) 250 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr)
309 251
310 COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value, 252 COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value,
311 T_is_refcounted_type_and_needs_scoped_refptr); 253 T_is_refcounted_type_and_needs_scoped_refptr);
312 254
313 public: 255 public:
314 // The element and deleter types. 256 // The element and deleter types.
315 typedef T element_type; 257 typedef T element_type;
316 typedef D deleter_type; 258 typedef D deleter_type;
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 scoped_ptr<T> make_scoped_ptr(T* ptr) { 520 scoped_ptr<T> make_scoped_ptr(T* ptr) {
579 return scoped_ptr<T>(ptr); 521 return scoped_ptr<T>(ptr);
580 } 522 }
581 523
582 template <typename T> 524 template <typename T>
583 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) { 525 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) {
584 return out << p.get(); 526 return out << p.get();
585 } 527 }
586 528
587 #endif // BASE_MEMORY_SCOPED_PTR_H_ 529 #endif // BASE_MEMORY_SCOPED_PTR_H_
OLDNEW
« no previous file with comments | « no previous file | base/memory/scoped_ptr_unittest.cc » ('j') | base/trace_event/memory_dump_manager.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698