| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 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 | |
| 7 // end of a scope. There are two main classes you will use, which coorespond | |
| 8 // to the operators new/delete and new[]/delete[]. | |
| 9 // | |
| 10 // Example usage (scoped_ptr): | |
| 11 // { | |
| 12 // scoped_ptr<Foo> foo(new Foo("wee")); | |
| 13 // } // foo goes out of scope, releasing the pointer with it. | |
| 14 // | |
| 15 // { | |
| 16 // scoped_ptr<Foo> foo; // No pointer managed. | |
| 17 // foo.reset(new Foo("wee")); // Now a pointer is managed. | |
| 18 // foo.reset(new Foo("wee2")); // Foo("wee") was destroyed. | |
| 19 // foo.reset(new Foo("wee3")); // Foo("wee2") was destroyed. | |
| 20 // foo->Method(); // Foo::Method() called. | |
| 21 // foo.get()->Method(); // Foo::Method() called. | |
| 22 // SomeFunc(foo.Release()); // SomeFunc takes owernship, foo no longer | |
| 23 // // manages a pointer. | |
| 24 // foo.reset(new Foo("wee4")); // foo manages a pointer again. | |
| 25 // foo.reset(); // Foo("wee4") destroyed, foo no longer | |
| 26 // // manages a pointer. | |
| 27 // } // foo wasn't managing a pointer, so nothing was destroyed. | |
| 28 // | |
| 29 // Example usage (scoped_array): | |
| 30 // { | |
| 31 // scoped_array<Foo> foo(new Foo[100]); | |
| 32 // foo.get()->Method(); // Foo::Method on the 0th element. | |
| 33 // foo[10].Method(); // Foo::Method on the 10th element. | |
| 34 // } | |
| 35 | |
| 36 #ifndef BASE_SCOPED_PTR_H_ | |
| 37 #define BASE_SCOPED_PTR_H_ | |
| 38 | |
| 39 // This is an implementation designed to match the anticipated future TR2 | |
| 40 // implementation of the scoped_ptr class, and its closely-related brethren, | |
| 41 // scoped_array, scoped_ptr_malloc. | |
| 42 | |
| 43 #include <assert.h> | |
| 44 #include <stdlib.h> | |
| 45 #include <cstddef> | |
| 46 | |
| 47 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> | |
| 48 // automatically deletes the pointer it holds (if any). | |
| 49 // That is, scoped_ptr<T> owns the T object that it points to. | |
| 50 // Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. | |
| 51 // Also like T*, scoped_ptr<T> is thread-compatible, and once you | |
| 52 // dereference it, you get the threadsafety guarantees of T. | |
| 53 // | |
| 54 // The size of a scoped_ptr is small: | |
| 55 // sizeof(scoped_ptr<C>) == sizeof(C*) | |
| 56 template <class C> | |
| 57 class scoped_ptr { | |
| 58 public: | |
| 59 | |
| 60 // The element type | |
| 61 typedef C element_type; | |
| 62 | |
| 63 // Constructor. Defaults to intializing with NULL. | |
| 64 // There is no way to create an uninitialized scoped_ptr. | |
| 65 // The input parameter must be allocated with new. | |
| 66 explicit scoped_ptr(C* p = NULL) : ptr_(p) { } | |
| 67 | |
| 68 // Destructor. If there is a C object, delete it. | |
| 69 // We don't need to test ptr_ == NULL because C++ does that for us. | |
| 70 ~scoped_ptr() { | |
| 71 enum { type_must_be_complete = sizeof(C) }; | |
| 72 delete ptr_; | |
| 73 } | |
| 74 | |
| 75 // Reset. Deletes the current owned object, if any. | |
| 76 // Then takes ownership of a new object, if given. | |
| 77 // this->reset(this->get()) works. | |
| 78 void reset(C* p = NULL) { | |
| 79 if (p != ptr_) { | |
| 80 enum { type_must_be_complete = sizeof(C) }; | |
| 81 delete ptr_; | |
| 82 ptr_ = p; | |
| 83 } | |
| 84 } | |
| 85 | |
| 86 // Accessors to get the owned object. | |
| 87 // operator* and operator-> will assert() if there is no current object. | |
| 88 C& operator*() const { | |
| 89 assert(ptr_ != NULL); | |
| 90 return *ptr_; | |
| 91 } | |
| 92 C* operator->() const { | |
| 93 assert(ptr_ != NULL); | |
| 94 return ptr_; | |
| 95 } | |
| 96 C* get() const { return ptr_; } | |
| 97 | |
| 98 // Comparison operators. | |
| 99 // These return whether two scoped_ptr refer to the same object, not just to | |
| 100 // two different but equal objects. | |
| 101 bool operator==(C* p) const { return ptr_ == p; } | |
| 102 bool operator!=(C* p) const { return ptr_ != p; } | |
| 103 | |
| 104 // Swap two scoped pointers. | |
| 105 void swap(scoped_ptr& p2) { | |
| 106 C* tmp = ptr_; | |
| 107 ptr_ = p2.ptr_; | |
| 108 p2.ptr_ = tmp; | |
| 109 } | |
| 110 | |
| 111 // Release a pointer. | |
| 112 // The return value is the current pointer held by this object. | |
| 113 // If this object holds a NULL pointer, the return value is NULL. | |
| 114 // After this operation, this object will hold a NULL pointer, | |
| 115 // and will not own the object any more. | |
| 116 C* release() { | |
| 117 C* retVal = ptr_; | |
| 118 ptr_ = NULL; | |
| 119 return retVal; | |
| 120 } | |
| 121 | |
| 122 private: | |
| 123 C* ptr_; | |
| 124 | |
| 125 // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't | |
| 126 // make sense, and if C2 == C, it still doesn't make sense because you should | |
| 127 // never have the same object owned by two different scoped_ptrs. | |
| 128 template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; | |
| 129 template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; | |
| 130 | |
| 131 // Disallow evil constructors | |
| 132 scoped_ptr(const scoped_ptr&); | |
| 133 void operator=(const scoped_ptr&); | |
| 134 }; | |
| 135 | |
| 136 // Free functions | |
| 137 template <class C> | |
| 138 void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) { | |
| 139 p1.swap(p2); | |
| 140 } | |
| 141 | |
| 142 template <class C> | |
| 143 bool operator==(C* p1, const scoped_ptr<C>& p2) { | |
| 144 return p1 == p2.get(); | |
| 145 } | |
| 146 | |
| 147 template <class C> | |
| 148 bool operator!=(C* p1, const scoped_ptr<C>& p2) { | |
| 149 return p1 != p2.get(); | |
| 150 } | |
| 151 | |
| 152 // scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate | |
| 153 // with new [] and the destructor deletes objects with delete []. | |
| 154 // | |
| 155 // As with scoped_ptr<C>, a scoped_array<C> either points to an object | |
| 156 // or is NULL. A scoped_array<C> owns the object that it points to. | |
| 157 // scoped_array<T> is thread-compatible, and once you index into it, | |
| 158 // the returned objects have only the threadsafety guarantees of T. | |
| 159 // | |
| 160 // Size: sizeof(scoped_array<C>) == sizeof(C*) | |
| 161 template <class C> | |
| 162 class scoped_array { | |
| 163 public: | |
| 164 | |
| 165 // The element type | |
| 166 typedef C element_type; | |
| 167 | |
| 168 // Constructor. Defaults to intializing with NULL. | |
| 169 // There is no way to create an uninitialized scoped_array. | |
| 170 // The input parameter must be allocated with new []. | |
| 171 explicit scoped_array(C* p = NULL) : array_(p) { } | |
| 172 | |
| 173 // Destructor. If there is a C object, delete it. | |
| 174 // We don't need to test ptr_ == NULL because C++ does that for us. | |
| 175 ~scoped_array() { | |
| 176 enum { type_must_be_complete = sizeof(C) }; | |
| 177 delete[] array_; | |
| 178 } | |
| 179 | |
| 180 // Reset. Deletes the current owned object, if any. | |
| 181 // Then takes ownership of a new object, if given. | |
| 182 // this->reset(this->get()) works. | |
| 183 void reset(C* p = NULL) { | |
| 184 if (p != array_) { | |
| 185 enum { type_must_be_complete = sizeof(C) }; | |
| 186 delete[] array_; | |
| 187 array_ = p; | |
| 188 } | |
| 189 } | |
| 190 | |
| 191 // Get one element of the current object. | |
| 192 // Will assert() if there is no current object, or index i is negative. | |
| 193 C& operator[](std::ptrdiff_t i) const { | |
| 194 assert(i >= 0); | |
| 195 assert(array_ != NULL); | |
| 196 return array_[i]; | |
| 197 } | |
| 198 | |
| 199 // Get a pointer to the zeroth element of the current object. | |
| 200 // If there is no current object, return NULL. | |
| 201 C* get() const { | |
| 202 return array_; | |
| 203 } | |
| 204 | |
| 205 // Comparison operators. | |
| 206 // These return whether two scoped_array refer to the same object, not just to | |
| 207 // two different but equal objects. | |
| 208 bool operator==(C* p) const { return array_ == p; } | |
| 209 bool operator!=(C* p) const { return array_ != p; } | |
| 210 | |
| 211 // Swap two scoped arrays. | |
| 212 void swap(scoped_array& p2) { | |
| 213 C* tmp = array_; | |
| 214 array_ = p2.array_; | |
| 215 p2.array_ = tmp; | |
| 216 } | |
| 217 | |
| 218 // Release an array. | |
| 219 // The return value is the current pointer held by this object. | |
| 220 // If this object holds a NULL pointer, the return value is NULL. | |
| 221 // After this operation, this object will hold a NULL pointer, | |
| 222 // and will not own the object any more. | |
| 223 C* release() { | |
| 224 C* retVal = array_; | |
| 225 array_ = NULL; | |
| 226 return retVal; | |
| 227 } | |
| 228 | |
| 229 private: | |
| 230 C* array_; | |
| 231 | |
| 232 // Forbid comparison of different scoped_array types. | |
| 233 template <class C2> bool operator==(scoped_array<C2> const& p2) const; | |
| 234 template <class C2> bool operator!=(scoped_array<C2> const& p2) const; | |
| 235 | |
| 236 // Disallow evil constructors | |
| 237 scoped_array(const scoped_array&); | |
| 238 void operator=(const scoped_array&); | |
| 239 }; | |
| 240 | |
| 241 // Free functions | |
| 242 template <class C> | |
| 243 void swap(scoped_array<C>& p1, scoped_array<C>& p2) { | |
| 244 p1.swap(p2); | |
| 245 } | |
| 246 | |
| 247 template <class C> | |
| 248 bool operator==(C* p1, const scoped_array<C>& p2) { | |
| 249 return p1 == p2.get(); | |
| 250 } | |
| 251 | |
| 252 template <class C> | |
| 253 bool operator!=(C* p1, const scoped_array<C>& p2) { | |
| 254 return p1 != p2.get(); | |
| 255 } | |
| 256 | |
| 257 // This class wraps the c library function free() in a class that can be | |
| 258 // passed as a template argument to scoped_ptr_malloc below. | |
| 259 class ScopedPtrMallocFree { | |
| 260 public: | |
| 261 inline void operator()(void* x) const { | |
| 262 free(x); | |
| 263 } | |
| 264 }; | |
| 265 | |
| 266 // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a | |
| 267 // second template argument, the functor used to free the object. | |
| 268 | |
| 269 template<class C, class FreeProc = ScopedPtrMallocFree> | |
| 270 class scoped_ptr_malloc { | |
| 271 public: | |
| 272 | |
| 273 // The element type | |
| 274 typedef C element_type; | |
| 275 | |
| 276 // Constructor. Defaults to intializing with NULL. | |
| 277 // There is no way to create an uninitialized scoped_ptr. | |
| 278 // The input parameter must be allocated with an allocator that matches the | |
| 279 // Free functor. For the default Free functor, this is malloc, calloc, or | |
| 280 // realloc. | |
| 281 explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {} | |
| 282 | |
| 283 // Destructor. If there is a C object, call the Free functor. | |
| 284 ~scoped_ptr_malloc() { | |
| 285 free_(ptr_); | |
| 286 } | |
| 287 | |
| 288 // Reset. Calls the Free functor on the current owned object, if any. | |
| 289 // Then takes ownership of a new object, if given. | |
| 290 // this->reset(this->get()) works. | |
| 291 void reset(C* p = NULL) { | |
| 292 if (ptr_ != p) { | |
| 293 free_(ptr_); | |
| 294 ptr_ = p; | |
| 295 } | |
| 296 } | |
| 297 | |
| 298 // Get the current object. | |
| 299 // operator* and operator-> will cause an assert() failure if there is | |
| 300 // no current object. | |
| 301 C& operator*() const { | |
| 302 assert(ptr_ != NULL); | |
| 303 return *ptr_; | |
| 304 } | |
| 305 | |
| 306 C* operator->() const { | |
| 307 assert(ptr_ != NULL); | |
| 308 return ptr_; | |
| 309 } | |
| 310 | |
| 311 C* get() const { | |
| 312 return ptr_; | |
| 313 } | |
| 314 | |
| 315 // Comparison operators. | |
| 316 // These return whether a scoped_ptr_malloc and a plain pointer refer | |
| 317 // to the same object, not just to two different but equal objects. | |
| 318 // For compatibility wwith the boost-derived implementation, these | |
| 319 // take non-const arguments. | |
| 320 bool operator==(C* p) const { | |
| 321 return ptr_ == p; | |
| 322 } | |
| 323 | |
| 324 bool operator!=(C* p) const { | |
| 325 return ptr_ != p; | |
| 326 } | |
| 327 | |
| 328 // Swap two scoped pointers. | |
| 329 void swap(scoped_ptr_malloc & b) { | |
| 330 C* tmp = b.ptr_; | |
| 331 b.ptr_ = ptr_; | |
| 332 ptr_ = tmp; | |
| 333 } | |
| 334 | |
| 335 // Release a pointer. | |
| 336 // The return value is the current pointer held by this object. | |
| 337 // If this object holds a NULL pointer, the return value is NULL. | |
| 338 // After this operation, this object will hold a NULL pointer, | |
| 339 // and will not own the object any more. | |
| 340 C* release() { | |
| 341 C* tmp = ptr_; | |
| 342 ptr_ = NULL; | |
| 343 return tmp; | |
| 344 } | |
| 345 | |
| 346 private: | |
| 347 C* ptr_; | |
| 348 | |
| 349 // no reason to use these: each scoped_ptr_malloc should have its own object | |
| 350 template <class C2, class GP> | |
| 351 bool operator==(scoped_ptr_malloc<C2, GP> const& p) const; | |
| 352 template <class C2, class GP> | |
| 353 bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const; | |
| 354 | |
| 355 static FreeProc const free_; | |
| 356 | |
| 357 // Disallow evil constructors | |
| 358 scoped_ptr_malloc(const scoped_ptr_malloc&); | |
| 359 void operator=(const scoped_ptr_malloc&); | |
| 360 }; | |
| 361 | |
| 362 template<class C, class FP> | |
| 363 FP const scoped_ptr_malloc<C, FP>::free_ = FP(); | |
| 364 | |
| 365 template<class C, class FP> inline | |
| 366 void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) { | |
| 367 a.swap(b); | |
| 368 } | |
| 369 | |
| 370 template<class C, class FP> inline | |
| 371 bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) { | |
| 372 return p == b.get(); | |
| 373 } | |
| 374 | |
| 375 template<class C, class FP> inline | |
| 376 bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) { | |
| 377 return p != b.get(); | |
| 378 } | |
| 379 | |
| 380 #endif // BASE_SCOPED_PTR_H_ | |
| OLD | NEW |