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

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

Issue 11149006: Extend scoped_ptr to be closer to unique_ptr. Support custom deleters, and deleting arrays. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix reset() to not call deleter on NULL ptr_. Matches unique_ptr<> spec. Created 8 years 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 | Annotate | Revision Log
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 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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 #define BASE_MEMORY_SCOPED_PTR_H_ 88 #define BASE_MEMORY_SCOPED_PTR_H_
89 89
90 // This is an implementation designed to match the anticipated future TR2 90 // This is an implementation designed to match the anticipated future TR2
91 // implementation of the scoped_ptr class, and its closely-related brethren, 91 // implementation of the scoped_ptr class, and its closely-related brethren,
92 // scoped_array, scoped_ptr_malloc. 92 // scoped_array, scoped_ptr_malloc.
93 93
94 #include <assert.h> 94 #include <assert.h>
95 #include <stddef.h> 95 #include <stddef.h>
96 #include <stdlib.h> 96 #include <stdlib.h>
97 97
98 #include <algorithm> // For std::swap().
99
98 #include "base/basictypes.h" 100 #include "base/basictypes.h"
99 #include "base/compiler_specific.h" 101 #include "base/compiler_specific.h"
100 #include "base/move.h" 102 #include "base/move.h"
101 #include "base/template_util.h" 103 #include "base/template_util.h"
102 104
103 namespace base { 105 namespace base {
104 106
105 namespace subtle { 107 namespace subtle {
106 class RefCountedBase; 108 class RefCountedBase;
107 class RefCountedThreadSafeBase; 109 class RefCountedThreadSafeBase;
108 } // namespace subtle 110 } // namespace subtle
109 111
112 // Function object which deletes its parameter, which must be a pointer.
113 // If C is an array type, invokes 'delete[]' on the parameter; otherwise,
114 // invokes 'delete'. The default deleter for scoped_ptr<T>.
115 template <class T>
116 struct DefaultDeleter {
117 DefaultDeleter() {}
118 template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) {
119 // All default single-object deleters can trivially convert to one another.
120 }
121 inline void operator()(T* ptr) const {
122 enum { type_must_be_complete = sizeof(T) };
123 delete ptr;
124 }
125 };
126
127 // Specialization of DefaultDeleter for array types.
128 template <class T>
129 struct DefaultDeleter<T[]> {
130 inline void operator()(T* ptr) const {
131 enum { type_must_be_complete = sizeof(T) };
132 delete[] ptr;
133 }
134
135 private:
136 // Disable this operator for any U != T because it is unsafe to execute
137 // an array delete when the static type of the array mismatches the dynamic
138 // type.
139 template <typename U> void operator()(U* array) const;
140 };
141
142 // Function object which invokes 'free' on its parameter, which must be
143 // a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
144 //
145 // scoped_ptr<int, base::FreeDeleter> foo_ptr(
146 // static_cast<int>(malloc(sizeof(int))));
Jeffrey Yasskin 2012/11/28 06:07:18 static_cast<int*>, right?
awong 2012/11/28 10:20:35 Right. :)
147 struct FreeDeleter {
148 inline void operator()(void* ptr) const {
Jeffrey Yasskin 2012/11/28 06:07:18 This isn't going to work on const or volatile poin
awong 2012/11/28 10:20:35 I don't think we care. This is basically staging a
149 free(ptr);
150 }
151 };
152
110 namespace internal { 153 namespace internal {
111 154
112 template <typename T> struct IsNotRefCounted { 155 template <typename T> struct IsNotRefCounted {
113 enum { 156 enum {
114 value = !base::is_convertible<T*, base::subtle::RefCountedBase*>::value && 157 value = !base::is_convertible<T*, base::subtle::RefCountedBase*>::value &&
115 !base::is_convertible<T*, base::subtle::RefCountedThreadSafeBase*>:: 158 !base::is_convertible<T*, base::subtle::RefCountedThreadSafeBase*>::
116 value 159 value
117 }; 160 };
118 }; 161 };
119 162
163 // Minimal implementation of the core logic of scoped_ptr, suitable for
164 // reuse in both scoped_ptr and its specializations.
165 template <class T, class D>
166 class scoped_ptr_impl {
167 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr_impl, RValue)
168
169 public:
170 explicit scoped_ptr_impl(T* p) : data_(p) { }
171
172 // Initializer for deleters that have data parameters.
173 scoped_ptr_impl(T* p, const D& d) : data_(p, d) {}
174
175 template <typename U, typename V>
176 scoped_ptr_impl(scoped_ptr_impl<U, V> other)
177 : data_(other.data_.ptr, other.data_) {
178 // We do not support move-only deleters. We could modify our move
179 // emulation to have base::subtle::move() and base::subtle::forward()
180 // functions that are imperfect emulations of their C++11 equivalents,
181 // but until there's a requirement, just assume deleters are copyable.
182 other.data_.ptr = NULL;
183 }
184
185 template <typename U, typename V>
186 const scoped_ptr_impl& operator=(scoped_ptr_impl<U, V> rhs) {
187 // See comment in move type-coverting constructor above regarding lack of
188 // support for move-only deleters.
189 reset(rhs.release());
190 get_deleter() = rhs.get_deleter();
191 return *this;
192 }
193
194 scoped_ptr_impl(RValue rvalue) : data_(rvalue.object->data_) {
195 rvalue.object->data_.ptr = NULL;
196 }
197
198 ~scoped_ptr_impl() {
199 if (data_.ptr != NULL) {
200 get_deleter()(data_.ptr);
201 }
202 }
203
204 void reset(T* p) {
205 // This self-reset check is deprecated.
206 // this->reset(this->get()) currently works, but it is DEPRECATED, and
207 // will be removed once we verify that no one depends on it.
208 //
209 // TODO(ajwong): Change this behavior to match unique_ptr<>.
210 // http://crbug.com/162971
211 if (p != data_.ptr) {
212 if (data_.ptr != NULL) {
213 // Note that this can lead to undefined behavior and memory leaks
214 // in the unlikely but possible case that get_deleter()(get())
215 // indirectly deletes this. The fix is to reset ptr_ before deleting
216 // its old value, but first we need to clean up the code that relies
217 // on the current sequencing.
218 get_deleter()(data_.ptr);
219 }
220 data_.ptr = p;
221 }
222 }
223
224 T* get() const { return data_.ptr; }
225
226 D& get_deleter() { return data_; }
227 const D& get_deleter() const { return data_; }
228
229 void swap(scoped_ptr_impl& p2) {
230 // Standard swap idiom: 'using std::swap' ensures that std::swap is
231 // present in the overload set, but we call swap unqualified so that
232 // any more-specific overloads can be used, if available.
233 using std::swap;
234 swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));
235 swap(data_.ptr, p2.data_.ptr);
236 }
237
238 T* release() {
239 T* old_ptr = data_.ptr;
240 data_.ptr = NULL;
241 return old_ptr;
242 }
243
244 private:
245 // Needed to allow type-converting constructor.
246 template <typename U, typename V> friend class scoped_ptr_impl;
247
248 // Use the empty base class optimization to allow us to have a D
249 // member, while avoiding any space overhead for it when D is an
250 // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
251 // discussion of this technique.
252 struct Data : public D {
253 explicit Data(T* ptr_in) : ptr(ptr_in) {}
254 Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {}
255 T* ptr;
256 };
257
258 Data data_;
259 };
260
120 } // namespace internal 261 } // namespace internal
262
121 } // namespace base 263 } // namespace base
122 264
123 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> 265 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
124 // automatically deletes the pointer it holds (if any). 266 // automatically deletes the pointer it holds (if any).
125 // That is, scoped_ptr<T> owns the T object that it points to. 267 // That is, scoped_ptr<T> owns the T object that it points to.
126 // Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. 268 // Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
127 // Also like T*, scoped_ptr<T> is thread-compatible, and once you 269 // Also like T*, scoped_ptr<T> is thread-compatible, and once you
128 // dereference it, you get the thread safety guarantees of T. 270 // dereference it, you get the thread safety guarantees of T.
129 // 271 //
130 // The size of a scoped_ptr is small: 272 // The size of a scoped_ptr is small:
131 // sizeof(scoped_ptr<C>) == sizeof(C*) 273 // sizeof(scoped_ptr<C>) == sizeof(C*)
132 template <class C> 274 template <class T, class D = base::DefaultDeleter<T> >
133 class scoped_ptr { 275 class scoped_ptr {
134 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) 276 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
135 277
136 COMPILE_ASSERT(base::internal::IsNotRefCounted<C>::value, 278 COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value,
137 C_is_refcounted_type_and_needs_scoped_refptr); 279 T_is_refcounted_type_and_needs_scoped_refptr);
138 280
139 public: 281 public:
140 282 // The element and deleter types.
141 // The element type 283 typedef T element_type;
142 typedef C element_type; 284 typedef D deleter_type;
143 285
144 // Constructor. Defaults to initializing with NULL. 286 // Constructor. Defaults to initializing with NULL.
145 // There is no way to create an uninitialized scoped_ptr. 287 scoped_ptr() : impl_(NULL) { }
146 // The input parameter must be allocated with new. 288
147 explicit scoped_ptr(C* p = NULL) : ptr_(p) { } 289 // Constructor. Takes ownership of p.
290 explicit scoped_ptr(element_type* p) : impl_(p) { }
291
292 // Constructor. Allows initialization of a stateful deleter.
293 scoped_ptr(element_type* p, const D& d) : impl_(p, d) { }
148 294
149 // Constructor. Allows construction from a scoped_ptr rvalue for a 295 // Constructor. Allows construction from a scoped_ptr rvalue for a
150 // convertible type. 296 // convertible type and deleter.
151 template <typename U> 297 template <typename U, typename V>
152 scoped_ptr(scoped_ptr<U> other) : ptr_(other.release()) { } 298 scoped_ptr(scoped_ptr<U, V> other) : impl_(other.impl_.Pass()) { }
153 299
154 // Constructor. Move constructor for C++03 move emulation of this type. 300 // Constructor. Move constructor for C++03 move emulation of this type.
155 scoped_ptr(RValue rvalue) 301 scoped_ptr(RValue rvalue) : impl_(rvalue.object->impl_.Pass()) { }
156 : ptr_(rvalue.object->release()) {
157 }
158
159 // Destructor. If there is a C object, delete it.
160 // We don't need to test ptr_ == NULL because C++ does that for us.
161 ~scoped_ptr() {
162 enum { type_must_be_complete = sizeof(C) };
163 delete ptr_;
164 }
165 302
166 // operator=. Allows assignment from a scoped_ptr rvalue for a convertible 303 // operator=. Allows assignment from a scoped_ptr rvalue for a convertible
167 // type. 304 // type and deleter.
168 template <typename U> 305 template <typename U, typename V>
169 scoped_ptr& operator=(scoped_ptr<U> rhs) { 306 scoped_ptr& operator=(scoped_ptr<U, V> rhs) {
170 reset(rhs.release()); 307 impl_ = rhs.impl_.Pass();
171 return *this; 308 return *this;
172 } 309 }
173 310
174 // operator=. Move operator= for C++03 move emulation of this type. 311 // Reset. Deletes the currently owned object, if any.
175 scoped_ptr& operator=(RValue rhs) {
176 swap(*rhs->object);
177 return *this;
178 }
179
180 // Reset. Deletes the current owned object, if any.
181 // Then takes ownership of a new object, if given. 312 // Then takes ownership of a new object, if given.
182 // this->reset(this->get()) works. 313 void reset(element_type* p = NULL) { impl_.reset(p); }
183 void reset(C* p = NULL) {
184 if (p != ptr_) {
185 enum { type_must_be_complete = sizeof(C) };
186 delete ptr_;
187 ptr_ = p;
188 }
189 }
190 314
191 // Accessors to get the owned object. 315 // Accessors to get the owned object.
192 // operator* and operator-> will assert() if there is no current object. 316 // operator* and operator-> will assert() if there is no current object.
193 C& operator*() const { 317 element_type& operator*() const {
194 assert(ptr_ != NULL); 318 assert(impl_.get() != NULL);
195 return *ptr_; 319 return *impl_.get();
196 } 320 }
197 C* operator->() const { 321 element_type* operator->() const {
198 assert(ptr_ != NULL); 322 assert(impl_.get() != NULL);
199 return ptr_; 323 return impl_.get();
200 } 324 }
201 C* get() const { return ptr_; } 325 element_type* get() const { return impl_.get(); }
202 326
203 // Allow scoped_ptr<C> to be used in boolean expressions, but not 327 // Access to the deleter.
328 deleter_type& get_deleter() { return impl_.get_deleter(); }
329 const deleter_type& get_deleter() const { return impl_.get_deleter(); }
330
331 // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
204 // implicitly convertible to a real bool (which is dangerous). 332 // implicitly convertible to a real bool (which is dangerous).
205 typedef C* scoped_ptr::*Testable; 333 private:
206 operator Testable() const { return ptr_ ? &scoped_ptr::ptr_ : NULL; } 334 typedef base::internal::scoped_ptr_impl<element_type, deleter_type>
335 scoped_ptr::*Testable;
336
337 public:
338 operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
207 339
208 // Comparison operators. 340 // Comparison operators.
209 // These return whether two scoped_ptr refer to the same object, not just to 341 // These return whether two scoped_ptr refer to the same object, not just to
210 // two different but equal objects. 342 // two different but equal objects.
211 bool operator==(C* p) const { return ptr_ == p; } 343 bool operator==(element_type* p) const { return impl_.get() == p; }
212 bool operator!=(C* p) const { return ptr_ != p; } 344 bool operator!=(element_type* p) const { return impl_.get() != p; }
213 345
214 // Swap two scoped pointers. 346 // Swap two scoped pointers.
215 void swap(scoped_ptr& p2) { 347 void swap(scoped_ptr& p2) {
216 C* tmp = ptr_; 348 impl_.swap(p2.impl_);
217 ptr_ = p2.ptr_;
218 p2.ptr_ = tmp;
219 } 349 }
220 350
221 // Release a pointer. 351 // Release a pointer.
222 // The return value is the current pointer held by this object. 352 // The return value is the current pointer held by this object.
223 // If this object holds a NULL pointer, the return value is NULL. 353 // If this object holds a NULL pointer, the return value is NULL.
224 // After this operation, this object will hold a NULL pointer, 354 // After this operation, this object will hold a NULL pointer,
225 // and will not own the object any more. 355 // and will not own the object any more.
226 C* release() WARN_UNUSED_RESULT { 356 element_type* release() WARN_UNUSED_RESULT {
227 C* retVal = ptr_; 357 return impl_.release();
228 ptr_ = NULL;
229 return retVal;
230 } 358 }
231 359
360 // C++98 doesn't support functions templates with default parameters which
361 // makes it hard to write a PassAs() that understands converting the deleter
362 // while preserving simple calling semantics.
363 //
364 // Until there is a use case for PassAs() with custom deleters, just ignore
365 // the custom deleter.
232 template <typename PassAsType> 366 template <typename PassAsType>
233 scoped_ptr<PassAsType> PassAs() { 367 scoped_ptr<PassAsType> PassAs() {
234 return scoped_ptr<PassAsType>(release()); 368 return scoped_ptr<PassAsType>(Pass());
235 } 369 }
236 370
237 private: 371 private:
238 C* ptr_; 372 // Needed to reach into |impl_| in the constructor.
373 template <typename U, typename V> friend class scoped_ptr;
374 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
239 375
240 // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't 376 // Forbid comparison of scoped_ptr types. If U != T, it totally
241 // make sense, and if C2 == C, it still doesn't make sense because you should 377 // doesn't make sense, and if U == T, it still doesn't make sense
242 // never have the same object owned by two different scoped_ptrs. 378 // because you should never have the same object owned by two different
243 template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; 379 // scoped_ptrs.
244 template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; 380 template <class U> bool operator==(scoped_ptr<U> const& p2) const;
381 template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
382 };
245 383
384 template <class T, class D>
385 class scoped_ptr<T[], D> {
386 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
387
388 public:
389 // The element and deleter types.
390 typedef T element_type;
391 typedef D deleter_type;
392
393 // Constructor. Defaults to initializing with NULL.
394 scoped_ptr() : impl_(NULL) { }
395
396 // Constructor. Stores the given array. Note that the argument's type
397 // must exactly match T*. In particular:
398 // - it cannot be a pointer to a type derived from T, because it is
399 // inherently unsafe to access an array through a pointer whose
400 // dynamic type does not match its static type. If you're doing this,
401 // fix your code.
402 // http://cplusplus.github.com/LWG/lwg-defects.html#938
403 // - it cannot be NULL, because NULL is an integral expression, not a
404 // pointer to T. Use the no-argument version instead of explicitly
405 // passing NULL.
406 // - it cannot be const-qualified differently from T per unique_ptr spec.
407 // http://cplusplus.github.com/LWG/lwg-active.html#2118
408 explicit scoped_ptr(element_type* array) : impl_(array) { }
409
410 // Constructor. Move constructor for C++03 move emulation of this type.
411 scoped_ptr(RValue rvalue) : impl_(rvalue.object->impl_.Pass()) { }
412
413 // operator=. Move operator= for C++03 move emulation of this type.
414 scoped_ptr& operator=(RValue rhs) {
415 impl_ = rhs.object->impl_.Pass();
416 return *this;
417 }
418
419 // Reset. Deletes the currently owned array, if any.
420 // Then takes ownership of a new object, if given.
421 void reset(element_type* array = NULL) { impl_.reset(array); }
422
423 // Accessors to get the owned array.
424 element_type& operator[](size_t i) const {
425 assert(impl_.get() != NULL);
426 return impl_.get()[i];
427 }
428 element_type* get() const { return impl_.get(); }
429
430 // Access to the deleter.
431 deleter_type& get_deleter() { return impl_.get_deleter(); }
432 const deleter_type& get_deleter() const { return impl_.get_deleter(); }
433
434 // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
435 // implicitly convertible to a real bool (which is dangerous).
436 private:
437 typedef base::internal::scoped_ptr_impl<element_type, deleter_type>
438 scoped_ptr::*Testable;
439
440 public:
441 operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
442
443 // Comparison operators.
444 // These return whether two scoped_ptr refer to the same object, not just to
445 // two different but equal objects.
446 bool operator==(element_type* array) const { return impl_.get() == array; }
447 bool operator!=(element_type* array) const { return impl_.get() != array; }
448
449 // Swap two scoped pointers.
450 void swap(scoped_ptr& p2) {
451 impl_.swap(p2.impl_);
452 }
453
454 // Release a pointer.
455 // The return value is the current pointer held by this object.
456 // If this object holds a NULL pointer, the return value is NULL.
457 // After this operation, this object will hold a NULL pointer,
458 // and will not own the object any more.
459 element_type* release() WARN_UNUSED_RESULT {
460 return impl_.release();
461 }
462
463 private:
464 // Force element_type to be a complete type.
465 enum { type_must_be_complete = sizeof(element_type) };
466
467 // Actually hold the data.
468 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
469
470 // Disable initialization from any type other than element_type*, by
471 // providing a constructor that matches such an initialization, but is
472 // private and has no definition. This is disabled because it is not safe to
473 // call delete[] on an array whose static type does not match its dynamic
474 // type.
475 template <typename U>
476 explicit scoped_ptr(U* array);
477
478 // Disable reset() from any type other than element_type*, for the same
479 // reasons as the constructor above.
480 template <typename U>
481 void reset(U* array);
482
483 // Forbid comparison of scoped_ptr types. If U != T, it totally
484 // doesn't make sense, and if U == T, it still doesn't make sense
485 // because you should never have the same object owned by two different
486 // scoped_ptrs.
487 template <class U> bool operator==(scoped_ptr<U> const& p2) const;
488 template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
246 }; 489 };
247 490
248 // Free functions 491 // Free functions
249 template <class C> 492 template <class T, class D>
250 void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) { 493 void swap(scoped_ptr<T, D>& p1, scoped_ptr<T, D>& p2) {
251 p1.swap(p2); 494 p1.swap(p2);
252 } 495 }
253 496
254 template <class C> 497 template <class T, class D>
255 bool operator==(C* p1, const scoped_ptr<C>& p2) { 498 bool operator==(T* p1, const scoped_ptr<T, D>& p2) {
256 return p1 == p2.get(); 499 return p1 == p2.get();
257 } 500 }
258 501
259 template <class C> 502 template <class T, class D>
260 bool operator!=(C* p1, const scoped_ptr<C>& p2) { 503 bool operator!=(T* p1, const scoped_ptr<T, D>& p2) {
261 return p1 != p2.get(); 504 return p1 != p2.get();
262 } 505 }
263 506
264 // scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate 507 // scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
Jeffrey Yasskin 2012/11/28 06:07:18 Should this be deprecated in favor of scoped_ptr<T
awong 2012/11/28 10:20:35 Yep. scoped_array and scoped_ptr_malloc should be
265 // with new [] and the destructor deletes objects with delete []. 508 // with new [] and the destructor deletes objects with delete [].
266 // 509 //
267 // As with scoped_ptr<C>, a scoped_array<C> either points to an object 510 // As with scoped_ptr<C>, a scoped_array<C> either points to an object
268 // or is NULL. A scoped_array<C> owns the object that it points to. 511 // or is NULL. A scoped_array<C> owns the object that it points to.
269 // scoped_array<T> is thread-compatible, and once you index into it, 512 // scoped_array<T> is thread-compatible, and once you index into it,
270 // the returned objects have only the thread safety guarantees of T. 513 // the returned objects have only the thread safety guarantees of T.
271 // 514 //
272 // Size: sizeof(scoped_array<C>) == sizeof(C*) 515 // Size: sizeof(scoped_array<C>) == sizeof(C*)
273 template <class C> 516 template <class C>
274 class scoped_array { 517 class scoped_array {
(...skipping 16 matching lines...) Expand all
291 534
292 // Destructor. If there is a C object, delete it. 535 // Destructor. If there is a C object, delete it.
293 // We don't need to test ptr_ == NULL because C++ does that for us. 536 // We don't need to test ptr_ == NULL because C++ does that for us.
294 ~scoped_array() { 537 ~scoped_array() {
295 enum { type_must_be_complete = sizeof(C) }; 538 enum { type_must_be_complete = sizeof(C) };
296 delete[] array_; 539 delete[] array_;
297 } 540 }
298 541
299 // operator=. Move operator= for C++03 move emulation of this type. 542 // operator=. Move operator= for C++03 move emulation of this type.
300 scoped_array& operator=(RValue rhs) { 543 scoped_array& operator=(RValue rhs) {
301 swap(*rhs.object); 544 reset(rhs.object->release());
302 return *this; 545 return *this;
303 } 546 }
304 547
305 // Reset. Deletes the current owned object, if any. 548 // Reset. Deletes the current owned object, if any.
306 // Then takes ownership of a new object, if given. 549 // Then takes ownership of a new object, if given.
307 // this->reset(this->get()) works. 550 // this->reset(this->get()) works.
308 void reset(C* p = NULL) { 551 void reset(C* p = NULL) {
309 if (p != array_) { 552 if (p != array_) {
310 enum { type_must_be_complete = sizeof(C) }; 553 if (array_ != NULL) {
Jeffrey Yasskin 2012/11/28 06:07:18 Note that delete[] does nothing if array_ is NULL,
awong 2012/11/28 10:20:35 yeah. Good point. I spent about an hour of headach
311 delete[] array_; 554 enum { type_must_be_complete = sizeof(C) };
555 delete[] array_;
556 }
312 array_ = p; 557 array_ = p;
313 } 558 }
314 } 559 }
315 560
316 // Get one element of the current object. 561 // Get one element of the current object.
317 // Will assert() if there is no current object, or index i is negative. 562 // Will assert() if there is no current object, or index i is negative.
318 C& operator[](ptrdiff_t i) const { 563 C& operator[](ptrdiff_t i) const {
319 assert(i >= 0); 564 assert(i >= 0);
320 assert(array_ != NULL); 565 assert(array_ != NULL);
321 return array_[i]; 566 return array_[i];
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 template <class C> 618 template <class C>
374 bool operator==(C* p1, const scoped_array<C>& p2) { 619 bool operator==(C* p1, const scoped_array<C>& p2) {
375 return p1 == p2.get(); 620 return p1 == p2.get();
376 } 621 }
377 622
378 template <class C> 623 template <class C>
379 bool operator!=(C* p1, const scoped_array<C>& p2) { 624 bool operator!=(C* p1, const scoped_array<C>& p2) {
380 return p1 != p2.get(); 625 return p1 != p2.get();
381 } 626 }
382 627
383 // This class wraps the c library function free() in a class that can be
384 // passed as a template argument to scoped_ptr_malloc below.
385 class ScopedPtrMallocFree {
386 public:
387 inline void operator()(void* x) const {
388 free(x);
389 }
390 };
391
392 // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a 628 // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
Jeffrey Yasskin 2012/11/28 06:07:18 Should this be deprecated in favor of scoped_ptr<T
awong 2012/11/28 10:20:35 Yes.
393 // second template argument, the functor used to free the object. 629 // second template argument, the functor used to free the object.
394 630
395 template<class C, class FreeProc = ScopedPtrMallocFree> 631 template<class C, class FreeProc = base::FreeDeleter>
396 class scoped_ptr_malloc { 632 class scoped_ptr_malloc {
397 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr_malloc, RValue) 633 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr_malloc, RValue)
398 634
399 public: 635 public:
400 636
401 // The element type 637 // The element type
402 typedef C element_type; 638 typedef C element_type;
403 639
404 // Constructor. Defaults to initializing with NULL. 640 // Constructor. Defaults to initializing with NULL.
405 // There is no way to create an uninitialized scoped_ptr. 641 // There is no way to create an uninitialized scoped_ptr.
406 // The input parameter must be allocated with an allocator that matches the 642 // The input parameter must be allocated with an allocator that matches the
407 // Free functor. For the default Free functor, this is malloc, calloc, or 643 // Free functor. For the default Free functor, this is malloc, calloc, or
408 // realloc. 644 // realloc.
409 explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {} 645 explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {}
410 646
411 // Constructor. Move constructor for C++03 move emulation of this type. 647 // Constructor. Move constructor for C++03 move emulation of this type.
412 scoped_ptr_malloc(RValue rvalue) 648 scoped_ptr_malloc(RValue rvalue)
413 : ptr_(rvalue.object->release()) { 649 : ptr_(rvalue.object->release()) {
414 } 650 }
415 651
416 // Destructor. If there is a C object, call the Free functor. 652 // Destructor. If there is a C object, call the Free functor.
417 ~scoped_ptr_malloc() { 653 ~scoped_ptr_malloc() {
418 reset(); 654 reset();
419 } 655 }
420 656
421 // operator=. Move operator= for C++03 move emulation of this type. 657 // operator=. Move operator= for C++03 move emulation of this type.
422 scoped_ptr_malloc& operator=(RValue rhs) { 658 scoped_ptr_malloc& operator=(RValue rhs) {
423 swap(*rhs.object); 659 reset(rhs.object->release());
424 return *this; 660 return *this;
425 } 661 }
426 662
427 // Reset. Calls the Free functor on the current owned object, if any. 663 // Reset. Calls the Free functor on the current owned object, if any.
428 // Then takes ownership of a new object, if given. 664 // Then takes ownership of a new object, if given.
429 // this->reset(this->get()) works. 665 // this->reset(this->get()) works.
430 void reset(C* p = NULL) { 666 void reset(C* p = NULL) {
431 if (ptr_ != p) { 667 if (ptr_ != p) {
432 FreeProc free_proc; 668 if (ptr_ != NULL) {
433 free_proc(ptr_); 669 FreeProc free_proc;
670 free_proc(ptr_);
671 }
434 ptr_ = p; 672 ptr_ = p;
435 } 673 }
436 } 674 }
437 675
438 // Get the current object. 676 // Get the current object.
439 // operator* and operator-> will cause an assert() failure if there is 677 // operator* and operator-> will cause an assert() failure if there is
440 // no current object. 678 // no current object.
441 C& operator*() const { 679 C& operator*() const {
442 assert(ptr_ != NULL); 680 assert(ptr_ != NULL);
443 return *ptr_; 681 return *ptr_;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 753
516 // A function to convert T* into scoped_ptr<T> 754 // A function to convert T* into scoped_ptr<T>
517 // Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation 755 // Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation
518 // for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg)) 756 // for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
519 template <typename T> 757 template <typename T>
520 scoped_ptr<T> make_scoped_ptr(T* ptr) { 758 scoped_ptr<T> make_scoped_ptr(T* ptr) {
521 return scoped_ptr<T>(ptr); 759 return scoped_ptr<T>(ptr);
522 } 760 }
523 761
524 #endif // BASE_MEMORY_SCOPED_PTR_H_ 762 #endif // BASE_MEMORY_SCOPED_PTR_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698