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