Home | History | Annotate | Download | only in common
      1 // Copyright 2013 Google Inc. All Rights Reserved.
      2 //
      3 // Redistribution and use in source and binary forms, with or without
      4 // modification, are permitted provided that the following conditions are
      5 // met:
      6 //
      7 //     * Redistributions of source code must retain the above copyright
      8 // notice, this list of conditions and the following disclaimer.
      9 //     * Redistributions in binary form must reproduce the above
     10 // copyright notice, this list of conditions and the following disclaimer
     11 // in the documentation and/or other materials provided with the
     12 // distribution.
     13 //     * Neither the name of Google Inc. nor the names of its
     14 // contributors may be used to endorse or promote products derived from
     15 // this software without specific prior written permission.
     16 //
     17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28 
     29 // Scopers help you manage ownership of a pointer, helping you easily manage the
     30 // a pointer within a scope, and automatically destroying the pointer at the
     31 // end of a scope.  There are two main classes you will use, which correspond
     32 // to the operators new/delete and new[]/delete[].
     33 //
     34 // Example usage (scoped_ptr):
     35 //   {
     36 //     scoped_ptr<Foo> foo(new Foo("wee"));
     37 //   }  // foo goes out of scope, releasing the pointer with it.
     38 //
     39 //   {
     40 //     scoped_ptr<Foo> foo;          // No pointer managed.
     41 //     foo.reset(new Foo("wee"));    // Now a pointer is managed.
     42 //     foo.reset(new Foo("wee2"));   // Foo("wee") was destroyed.
     43 //     foo.reset(new Foo("wee3"));   // Foo("wee2") was destroyed.
     44 //     foo->Method();                // Foo::Method() called.
     45 //     foo.get()->Method();          // Foo::Method() called.
     46 //     SomeFunc(foo.release());      // SomeFunc takes ownership, foo no longer
     47 //                                   // manages a pointer.
     48 //     foo.reset(new Foo("wee4"));   // foo manages a pointer again.
     49 //     foo.reset();                  // Foo("wee4") destroyed, foo no longer
     50 //                                   // manages a pointer.
     51 //   }  // foo wasn't managing a pointer, so nothing was destroyed.
     52 //
     53 // Example usage (scoped_array):
     54 //   {
     55 //     scoped_array<Foo> foo(new Foo[100]);
     56 //     foo.get()->Method();  // Foo::Method on the 0th element.
     57 //     foo[10].Method();     // Foo::Method on the 10th element.
     58 //   }
     59 
     60 #ifndef COMMON_SCOPED_PTR_H_
     61 #define COMMON_SCOPED_PTR_H_
     62 
     63 // This is an implementation designed to match the anticipated future TR2
     64 // implementation of the scoped_ptr class, and its closely-related brethren,
     65 // scoped_array, scoped_ptr_malloc.
     66 
     67 #include <assert.h>
     68 #include <stddef.h>
     69 #include <stdlib.h>
     70 
     71 namespace google_breakpad {
     72 
     73 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
     74 // automatically deletes the pointer it holds (if any).
     75 // That is, scoped_ptr<T> owns the T object that it points to.
     76 // Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
     77 // Also like T*, scoped_ptr<T> is thread-compatible, and once you
     78 // dereference it, you get the threadsafety guarantees of T.
     79 //
     80 // The size of a scoped_ptr is small:
     81 // sizeof(scoped_ptr<C>) == sizeof(C*)
     82 template <class C>
     83 class scoped_ptr {
     84  public:
     85 
     86   // The element type
     87   typedef C element_type;
     88 
     89   // Constructor.  Defaults to initializing with NULL.
     90   // There is no way to create an uninitialized scoped_ptr.
     91   // The input parameter must be allocated with new.
     92   explicit scoped_ptr(C* p = NULL) : ptr_(p) { }
     93 
     94   // Destructor.  If there is a C object, delete it.
     95   // We don't need to test ptr_ == NULL because C++ does that for us.
     96   ~scoped_ptr() {
     97     enum { type_must_be_complete = sizeof(C) };
     98     delete ptr_;
     99   }
    100 
    101   // Reset.  Deletes the current owned object, if any.
    102   // Then takes ownership of a new object, if given.
    103   // this->reset(this->get()) works.
    104   void reset(C* p = NULL) {
    105     if (p != ptr_) {
    106       enum { type_must_be_complete = sizeof(C) };
    107       delete ptr_;
    108       ptr_ = p;
    109     }
    110   }
    111 
    112   // Accessors to get the owned object.
    113   // operator* and operator-> will assert() if there is no current object.
    114   C& operator*() const {
    115     assert(ptr_ != NULL);
    116     return *ptr_;
    117   }
    118   C* operator->() const  {
    119     assert(ptr_ != NULL);
    120     return ptr_;
    121   }
    122   C* get() const { return ptr_; }
    123 
    124   // Comparison operators.
    125   // These return whether two scoped_ptr refer to the same object, not just to
    126   // two different but equal objects.
    127   bool operator==(C* p) const { return ptr_ == p; }
    128   bool operator!=(C* p) const { return ptr_ != p; }
    129 
    130   // Swap two scoped pointers.
    131   void swap(scoped_ptr& p2) {
    132     C* tmp = ptr_;
    133     ptr_ = p2.ptr_;
    134     p2.ptr_ = tmp;
    135   }
    136 
    137   // Release a pointer.
    138   // The return value is the current pointer held by this object.
    139   // If this object holds a NULL pointer, the return value is NULL.
    140   // After this operation, this object will hold a NULL pointer,
    141   // and will not own the object any more.
    142   C* release() {
    143     C* retVal = ptr_;
    144     ptr_ = NULL;
    145     return retVal;
    146   }
    147 
    148  private:
    149   C* ptr_;
    150 
    151   // Forbid comparison of scoped_ptr types.  If C2 != C, it totally doesn't
    152   // make sense, and if C2 == C, it still doesn't make sense because you should
    153   // never have the same object owned by two different scoped_ptrs.
    154   template <class C2> bool operator==(scoped_ptr<C2> const& p2) const;
    155   template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const;
    156 
    157   // Disallow evil constructors
    158   scoped_ptr(const scoped_ptr&);
    159   void operator=(const scoped_ptr&);
    160 };
    161 
    162 // Free functions
    163 template <class C>
    164 void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) {
    165   p1.swap(p2);
    166 }
    167 
    168 template <class C>
    169 bool operator==(C* p1, const scoped_ptr<C>& p2) {
    170   return p1 == p2.get();
    171 }
    172 
    173 template <class C>
    174 bool operator!=(C* p1, const scoped_ptr<C>& p2) {
    175   return p1 != p2.get();
    176 }
    177 
    178 // scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
    179 // with new [] and the destructor deletes objects with delete [].
    180 //
    181 // As with scoped_ptr<C>, a scoped_array<C> either points to an object
    182 // or is NULL.  A scoped_array<C> owns the object that it points to.
    183 // scoped_array<T> is thread-compatible, and once you index into it,
    184 // the returned objects have only the threadsafety guarantees of T.
    185 //
    186 // Size: sizeof(scoped_array<C>) == sizeof(C*)
    187 template <class C>
    188 class scoped_array {
    189  public:
    190 
    191   // The element type
    192   typedef C element_type;
    193 
    194   // Constructor.  Defaults to intializing with NULL.
    195   // There is no way to create an uninitialized scoped_array.
    196   // The input parameter must be allocated with new [].
    197   explicit scoped_array(C* p = NULL) : array_(p) { }
    198 
    199   // Destructor.  If there is a C object, delete it.
    200   // We don't need to test ptr_ == NULL because C++ does that for us.
    201   ~scoped_array() {
    202     enum { type_must_be_complete = sizeof(C) };
    203     delete[] array_;
    204   }
    205 
    206   // Reset.  Deletes the current owned object, if any.
    207   // Then takes ownership of a new object, if given.
    208   // this->reset(this->get()) works.
    209   void reset(C* p = NULL) {
    210     if (p != array_) {
    211       enum { type_must_be_complete = sizeof(C) };
    212       delete[] array_;
    213       array_ = p;
    214     }
    215   }
    216 
    217   // Get one element of the current object.
    218   // Will assert() if there is no current object, or index i is negative.
    219   C& operator[](ptrdiff_t i) const {
    220     assert(i >= 0);
    221     assert(array_ != NULL);
    222     return array_[i];
    223   }
    224 
    225   // Get a pointer to the zeroth element of the current object.
    226   // If there is no current object, return NULL.
    227   C* get() const {
    228     return array_;
    229   }
    230 
    231   // Comparison operators.
    232   // These return whether two scoped_array refer to the same object, not just to
    233   // two different but equal objects.
    234   bool operator==(C* p) const { return array_ == p; }
    235   bool operator!=(C* p) const { return array_ != p; }
    236 
    237   // Swap two scoped arrays.
    238   void swap(scoped_array& p2) {
    239     C* tmp = array_;
    240     array_ = p2.array_;
    241     p2.array_ = tmp;
    242   }
    243 
    244   // Release an array.
    245   // The return value is the current pointer held by this object.
    246   // If this object holds a NULL pointer, the return value is NULL.
    247   // After this operation, this object will hold a NULL pointer,
    248   // and will not own the object any more.
    249   C* release() {
    250     C* retVal = array_;
    251     array_ = NULL;
    252     return retVal;
    253   }
    254 
    255  private:
    256   C* array_;
    257 
    258   // Forbid comparison of different scoped_array types.
    259   template <class C2> bool operator==(scoped_array<C2> const& p2) const;
    260   template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
    261 
    262   // Disallow evil constructors
    263   scoped_array(const scoped_array&);
    264   void operator=(const scoped_array&);
    265 };
    266 
    267 // Free functions
    268 template <class C>
    269 void swap(scoped_array<C>& p1, scoped_array<C>& p2) {
    270   p1.swap(p2);
    271 }
    272 
    273 template <class C>
    274 bool operator==(C* p1, const scoped_array<C>& p2) {
    275   return p1 == p2.get();
    276 }
    277 
    278 template <class C>
    279 bool operator!=(C* p1, const scoped_array<C>& p2) {
    280   return p1 != p2.get();
    281 }
    282 
    283 // This class wraps the c library function free() in a class that can be
    284 // passed as a template argument to scoped_ptr_malloc below.
    285 class ScopedPtrMallocFree {
    286  public:
    287   inline void operator()(void* x) const {
    288     free(x);
    289   }
    290 };
    291 
    292 // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
    293 // second template argument, the functor used to free the object.
    294 
    295 template<class C, class FreeProc = ScopedPtrMallocFree>
    296 class scoped_ptr_malloc {
    297  public:
    298 
    299   // The element type
    300   typedef C element_type;
    301 
    302   // Constructor.  Defaults to initializing with NULL.
    303   // There is no way to create an uninitialized scoped_ptr.
    304   // The input parameter must be allocated with an allocator that matches the
    305   // Free functor.  For the default Free functor, this is malloc, calloc, or
    306   // realloc.
    307   explicit scoped_ptr_malloc(C* p = NULL): ptr_(p) {}
    308 
    309   // Destructor.  If there is a C object, call the Free functor.
    310   ~scoped_ptr_malloc() {
    311     reset();
    312   }
    313 
    314   // Reset.  Calls the Free functor on the current owned object, if any.
    315   // Then takes ownership of a new object, if given.
    316   // this->reset(this->get()) works.
    317   void reset(C* p = NULL) {
    318     if (ptr_ != p) {
    319       FreeProc free_proc;
    320       free_proc(ptr_);
    321       ptr_ = p;
    322     }
    323   }
    324 
    325   // Get the current object.
    326   // operator* and operator-> will cause an assert() failure if there is
    327   // no current object.
    328   C& operator*() const {
    329     assert(ptr_ != NULL);
    330     return *ptr_;
    331   }
    332 
    333   C* operator->() const {
    334     assert(ptr_ != NULL);
    335     return ptr_;
    336   }
    337 
    338   C* get() const {
    339     return ptr_;
    340   }
    341 
    342   // Comparison operators.
    343   // These return whether a scoped_ptr_malloc and a plain pointer refer
    344   // to the same object, not just to two different but equal objects.
    345   // For compatibility with the boost-derived implementation, these
    346   // take non-const arguments.
    347   bool operator==(C* p) const {
    348     return ptr_ == p;
    349   }
    350 
    351   bool operator!=(C* p) const {
    352     return ptr_ != p;
    353   }
    354 
    355   // Swap two scoped pointers.
    356   void swap(scoped_ptr_malloc & b) {
    357     C* tmp = b.ptr_;
    358     b.ptr_ = ptr_;
    359     ptr_ = tmp;
    360   }
    361 
    362   // Release a pointer.
    363   // The return value is the current pointer held by this object.
    364   // If this object holds a NULL pointer, the return value is NULL.
    365   // After this operation, this object will hold a NULL pointer,
    366   // and will not own the object any more.
    367   C* release() {
    368     C* tmp = ptr_;
    369     ptr_ = NULL;
    370     return tmp;
    371   }
    372 
    373  private:
    374   C* ptr_;
    375 
    376   // no reason to use these: each scoped_ptr_malloc should have its own object
    377   template <class C2, class GP>
    378   bool operator==(scoped_ptr_malloc<C2, GP> const& p) const;
    379   template <class C2, class GP>
    380   bool operator!=(scoped_ptr_malloc<C2, GP> const& p) const;
    381 
    382   // Disallow evil constructors
    383   scoped_ptr_malloc(const scoped_ptr_malloc&);
    384   void operator=(const scoped_ptr_malloc&);
    385 };
    386 
    387 template<class C, class FP> inline
    388 void swap(scoped_ptr_malloc<C, FP>& a, scoped_ptr_malloc<C, FP>& b) {
    389   a.swap(b);
    390 }
    391 
    392 template<class C, class FP> inline
    393 bool operator==(C* p, const scoped_ptr_malloc<C, FP>& b) {
    394   return p == b.get();
    395 }
    396 
    397 template<class C, class FP> inline
    398 bool operator!=(C* p, const scoped_ptr_malloc<C, FP>& b) {
    399   return p != b.get();
    400 }
    401 
    402 }  // namespace google_breakpad
    403 
    404 #endif  // COMMON_SCOPED_PTR_H_
    405