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 "movable 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 function 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 // // No need for calling Pass() because we are constructing a temporary |
| 49 // // for the return value. |
| 50 // return scoped_ptr<Foo>(new Foo("new")); |
| 51 // } |
| 52 // scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) { |
| 53 // return arg.Pass(); |
| 54 // } |
| 55 // |
| 56 // { |
| 57 // scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay)" |
| 58 // TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay"). |
| 59 // scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo. |
| 60 // scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2. |
| 61 // PassThru(ptr2.Pass()); // ptr2 is correspondingly NULL. |
| 62 // } |
| 63 // |
| 64 // Notice that if you do not call Pass() when returning from PassThru(), or |
| 65 // when invoking TakesOwnership(), the code will not compile because scopers |
| 66 // are not copyable; they only implement move semantics which require calling |
| 67 // the Pass() function to signify a destructive transfer of state. CreateFoo() |
| 68 // is different though because we are constructing a temporary on the return |
| 69 // line and thus can avoid needing to call Pass(). |
35 | 70 |
36 #ifndef BASE_MEMORY_SCOPED_PTR_H_ | 71 #ifndef BASE_MEMORY_SCOPED_PTR_H_ |
37 #define BASE_MEMORY_SCOPED_PTR_H_ | 72 #define BASE_MEMORY_SCOPED_PTR_H_ |
38 #pragma once | 73 #pragma once |
39 | 74 |
40 // This is an implementation designed to match the anticipated future TR2 | 75 // This is an implementation designed to match the anticipated future TR2 |
41 // implementation of the scoped_ptr class, and its closely-related brethren, | 76 // implementation of the scoped_ptr class, and its closely-related brethren, |
42 // scoped_array, scoped_ptr_malloc. | 77 // scoped_array, scoped_ptr_malloc. |
43 | 78 |
44 #include <assert.h> | 79 #include <assert.h> |
45 #include <stddef.h> | 80 #include <stddef.h> |
46 #include <stdlib.h> | 81 #include <stdlib.h> |
47 | 82 |
48 #include "base/compiler_specific.h" | 83 #include "base/compiler_specific.h" |
49 | 84 |
| 85 // Macro with the boilerplate C++03 move emulation for a class. |
| 86 // |
| 87 // In C++11, this is done via rvalue references. Here, we use C++03 move |
| 88 // emulation to fake an rvalue reference. For a more thorough explanation |
| 89 // of the technique, see: |
| 90 // |
| 91 // http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Move_Constructor |
| 92 // |
| 93 #define CPP_03_MOVE_EMULATION(scoper, field) \ |
| 94 private: \ |
| 95 struct RValue { \ |
| 96 explicit RValue(scoper& obj) : obj_(obj) {} \ |
| 97 scoper& obj_; \ |
| 98 }; \ |
| 99 public: \ |
| 100 operator RValue() { return RValue(*this); } \ |
| 101 scoper(RValue proxy) : field(proxy.obj_.release()) { } \ |
| 102 scoper& operator=(RValue proxy) { \ |
| 103 swap(proxy.obj_); \ |
| 104 return *this; \ |
| 105 } \ |
| 106 scoper Pass() { return scoper(RValue(*this)); } |
| 107 |
50 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> | 108 // 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). | 109 // automatically deletes the pointer it holds (if any). |
52 // That is, scoped_ptr<T> owns the T object that it points to. | 110 // 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. | 111 // 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 | 112 // Also like T*, scoped_ptr<T> is thread-compatible, and once you |
55 // dereference it, you get the threadsafety guarantees of T. | 113 // dereference it, you get the thread safety guarantees of T. |
56 // | 114 // |
57 // The size of a scoped_ptr is small: | 115 // The size of a scoped_ptr is small: |
58 // sizeof(scoped_ptr<C>) == sizeof(C*) | 116 // sizeof(scoped_ptr<C>) == sizeof(C*) |
59 template <class C> | 117 template <class C> |
60 class scoped_ptr { | 118 class scoped_ptr { |
61 public: | 119 public: |
62 | 120 |
63 // The element type | 121 // The element type |
64 typedef C element_type; | 122 typedef C element_type; |
65 | 123 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 // The return value is the current pointer held by this object. | 173 // The return value is the current pointer held by this object. |
116 // If this object holds a NULL pointer, the return value is NULL. | 174 // If this object holds a NULL pointer, the return value is NULL. |
117 // After this operation, this object will hold a NULL pointer, | 175 // After this operation, this object will hold a NULL pointer, |
118 // and will not own the object any more. | 176 // and will not own the object any more. |
119 C* release() WARN_UNUSED_RESULT { | 177 C* release() WARN_UNUSED_RESULT { |
120 C* retVal = ptr_; | 178 C* retVal = ptr_; |
121 ptr_ = NULL; | 179 ptr_ = NULL; |
122 return retVal; | 180 return retVal; |
123 } | 181 } |
124 | 182 |
| 183 CPP_03_MOVE_EMULATION(scoped_ptr, ptr_); |
| 184 |
125 private: | 185 private: |
126 C* ptr_; | 186 C* ptr_; |
127 | 187 |
128 // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't | 188 // 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 | 189 // 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. | 190 // never have the same object owned by two different scoped_ptrs. |
131 template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; | 191 template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; |
132 template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; | 192 template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; |
133 | 193 |
134 // Disallow evil constructors | 194 // Disallow evil constructors. Note that MUST NOT take a const& because we |
135 scoped_ptr(const scoped_ptr&); | 195 // are implementing move semantics. See the CPP_03_MOVE_EMULATION macro. |
136 void operator=(const scoped_ptr&); | 196 scoped_ptr(scoped_ptr&); |
| 197 void operator=(scoped_ptr&); |
137 }; | 198 }; |
138 | 199 |
139 // Free functions | 200 // Free functions |
140 template <class C> | 201 template <class C> |
141 void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) { | 202 void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) { |
142 p1.swap(p2); | 203 p1.swap(p2); |
143 } | 204 } |
144 | 205 |
145 template <class C> | 206 template <class C> |
146 bool operator==(C* p1, const scoped_ptr<C>& p2) { | 207 bool operator==(C* p1, const scoped_ptr<C>& p2) { |
147 return p1 == p2.get(); | 208 return p1 == p2.get(); |
148 } | 209 } |
149 | 210 |
150 template <class C> | 211 template <class C> |
151 bool operator!=(C* p1, const scoped_ptr<C>& p2) { | 212 bool operator!=(C* p1, const scoped_ptr<C>& p2) { |
152 return p1 != p2.get(); | 213 return p1 != p2.get(); |
153 } | 214 } |
154 | 215 |
155 // scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate | 216 // scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate |
156 // with new [] and the destructor deletes objects with delete []. | 217 // with new [] and the destructor deletes objects with delete []. |
157 // | 218 // |
158 // As with scoped_ptr<C>, a scoped_array<C> either points to an object | 219 // As with scoped_ptr<C>, a scoped_array<C> either points to an object |
159 // or is NULL. A scoped_array<C> owns the object that it points to. | 220 // or is NULL. A scoped_array<C> owns the object that it points to. |
160 // scoped_array<T> is thread-compatible, and once you index into it, | 221 // scoped_array<T> is thread-compatible, and once you index into it, |
161 // the returned objects have only the threadsafety guarantees of T. | 222 // the returned objects have only the thread safety guarantees of T. |
162 // | 223 // |
163 // Size: sizeof(scoped_array<C>) == sizeof(C*) | 224 // Size: sizeof(scoped_array<C>) == sizeof(C*) |
164 template <class C> | 225 template <class C> |
165 class scoped_array { | 226 class scoped_array { |
166 public: | 227 public: |
167 | 228 |
168 // The element type | 229 // The element type |
169 typedef C element_type; | 230 typedef C element_type; |
170 | 231 |
171 // Constructor. Defaults to intializing with NULL. | 232 // Constructor. Defaults to initializing with NULL. |
172 // There is no way to create an uninitialized scoped_array. | 233 // There is no way to create an uninitialized scoped_array. |
173 // The input parameter must be allocated with new []. | 234 // The input parameter must be allocated with new []. |
174 explicit scoped_array(C* p = NULL) : array_(p) { } | 235 explicit scoped_array(C* p = NULL) : array_(p) { } |
175 | 236 |
176 // Destructor. If there is a C object, delete it. | 237 // Destructor. If there is a C object, delete it. |
177 // We don't need to test ptr_ == NULL because C++ does that for us. | 238 // We don't need to test ptr_ == NULL because C++ does that for us. |
178 ~scoped_array() { | 239 ~scoped_array() { |
179 enum { type_must_be_complete = sizeof(C) }; | 240 enum { type_must_be_complete = sizeof(C) }; |
180 delete[] array_; | 241 delete[] array_; |
181 } | 242 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 // The return value is the current pointer held by this object. | 283 // The return value is the current pointer held by this object. |
223 // If this object holds a NULL pointer, the return value is NULL. | 284 // If this object holds a NULL pointer, the return value is NULL. |
224 // After this operation, this object will hold a NULL pointer, | 285 // After this operation, this object will hold a NULL pointer, |
225 // and will not own the object any more. | 286 // and will not own the object any more. |
226 C* release() WARN_UNUSED_RESULT { | 287 C* release() WARN_UNUSED_RESULT { |
227 C* retVal = array_; | 288 C* retVal = array_; |
228 array_ = NULL; | 289 array_ = NULL; |
229 return retVal; | 290 return retVal; |
230 } | 291 } |
231 | 292 |
| 293 CPP_03_MOVE_EMULATION(scoped_array, array_); |
| 294 |
232 private: | 295 private: |
233 C* array_; | 296 C* array_; |
234 | 297 |
235 // Forbid comparison of different scoped_array types. | 298 // Forbid comparison of different scoped_array types. |
236 template <class C2> bool operator==(scoped_array<C2> const& p2) const; | 299 template <class C2> bool operator==(scoped_array<C2> const& p2) const; |
237 template <class C2> bool operator!=(scoped_array<C2> const& p2) const; | 300 template <class C2> bool operator!=(scoped_array<C2> const& p2) const; |
238 | 301 |
239 // Disallow evil constructors | 302 // Disallow evil constructors. Note that MUST NOT take a const& because we |
240 scoped_array(const scoped_array&); | 303 // are implementing move semantics. See the CPP_03_MOVE_EMULATION macro. |
241 void operator=(const scoped_array&); | 304 scoped_array(scoped_array&); |
| 305 void operator=(scoped_array&); |
242 }; | 306 }; |
243 | 307 |
244 // Free functions | 308 // Free functions |
245 template <class C> | 309 template <class C> |
246 void swap(scoped_array<C>& p1, scoped_array<C>& p2) { | 310 void swap(scoped_array<C>& p1, scoped_array<C>& p2) { |
247 p1.swap(p2); | 311 p1.swap(p2); |
248 } | 312 } |
249 | 313 |
250 template <class C> | 314 template <class C> |
251 bool operator==(C* p1, const scoped_array<C>& p2) { | 315 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. | 404 // The return value is the current pointer held by this object. |
341 // If this object holds a NULL pointer, the return value is NULL. | 405 // If this object holds a NULL pointer, the return value is NULL. |
342 // After this operation, this object will hold a NULL pointer, | 406 // After this operation, this object will hold a NULL pointer, |
343 // and will not own the object any more. | 407 // and will not own the object any more. |
344 C* release() WARN_UNUSED_RESULT { | 408 C* release() WARN_UNUSED_RESULT { |
345 C* tmp = ptr_; | 409 C* tmp = ptr_; |
346 ptr_ = NULL; | 410 ptr_ = NULL; |
347 return tmp; | 411 return tmp; |
348 } | 412 } |
349 | 413 |
| 414 CPP_03_MOVE_EMULATION(scoped_ptr_malloc, ptr_); |
| 415 |
350 private: | 416 private: |
351 C* ptr_; | 417 C* ptr_; |
352 | 418 |
353 // no reason to use these: each scoped_ptr_malloc should have its own object | 419 // no reason to use these: each scoped_ptr_malloc should have its own object |
354 template <class C2, class GP> | 420 template <class C2, class GP> |
355 bool operator==(scoped_ptr_malloc<C2, GP> const& p) const; | 421 bool operator==(scoped_ptr_malloc<C2, GP> const& p) const; |
356 template <class C2, class GP> | 422 template <class C2, class GP> |
357 bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const; | 423 bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const; |
358 | 424 |
359 // Disallow evil constructors | 425 // Disallow evil constructors. Note that MUST NOT take a const& because we |
360 scoped_ptr_malloc(const scoped_ptr_malloc&); | 426 // are implementing move semantics. See the CPP_03_MOVE_EMULATION macro. |
361 void operator=(const scoped_ptr_malloc&); | 427 scoped_ptr_malloc(scoped_ptr_malloc&); |
| 428 void operator=(scoped_ptr_malloc&); |
362 }; | 429 }; |
363 | 430 |
| 431 #undef CPP_03_MOVE_EMULATION |
| 432 |
364 template<class C, class FP> inline | 433 template<class C, class FP> inline |
365 void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) { | 434 void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) { |
366 a.swap(b); | 435 a.swap(b); |
367 } | 436 } |
368 | 437 |
369 template<class C, class FP> inline | 438 template<class C, class FP> inline |
370 bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) { | 439 bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) { |
371 return p == b.get(); | 440 return p == b.get(); |
372 } | 441 } |
373 | 442 |
374 template<class C, class FP> inline | 443 template<class C, class FP> inline |
375 bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) { | 444 bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) { |
376 return p != b.get(); | 445 return p != b.get(); |
377 } | 446 } |
378 | 447 |
379 #endif // BASE_MEMORY_SCOPED_PTR_H_ | 448 #endif // BASE_MEMORY_SCOPED_PTR_H_ |
OLD | NEW |