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*) 56template <class C> 57class 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 137template <class C> 138void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) { 139 p1.swap(p2); 140} 141 142template <class C> 143bool operator==(C* p1, const scoped_ptr<C>& p2) { 144 return p1 == p2.get(); 145} 146 147template <class C> 148bool 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*) 161template <class C> 162class 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 242template <class C> 243void swap(scoped_array<C>& p1, scoped_array<C>& p2) { 244 p1.swap(p2); 245} 246 247template <class C> 248bool operator==(C* p1, const scoped_array<C>& p2) { 249 return p1 == p2.get(); 250} 251 252template <class C> 253bool 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. 259class 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 269template<class C, class FreeProc = ScopedPtrMallocFree> 270class 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 362template<class C, class FP> 363FP const scoped_ptr_malloc<C, FP>::free_ = FP(); 364 365template<class C, class FP> inline 366void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) { 367 a.swap(b); 368} 369 370template<class C, class FP> inline 371bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) { 372 return p == b.get(); 373} 374 375template<class C, class FP> inline 376bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) { 377 return p != b.get(); 378} 379 380#endif // BASE_SCOPED_PTR_H_ 381