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