Home | History | Annotate | Download | only in base
      1 //  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
      2 //  Copyright (c) 2001, 2002 Peter Dimov
      3 //
      4 //  Permission to copy, use, modify, sell and distribute this software
      5 //  is granted provided this copyright notice appears in all copies.
      6 //  This software is provided "as is" without express or implied
      7 //  warranty, and with no claim as to its suitability for any purpose.
      8 //
      9 //  See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation.
     10 //
     11 
     12 //  scoped_ptr mimics a built-in pointer except that it guarantees deletion
     13 //  of the object pointed to, either on destruction of the scoped_ptr or via
     14 //  an explicit reset(). scoped_ptr is a simple solution for simple needs;
     15 //  use shared_ptr or std::auto_ptr if your needs are more complex.
     16 
     17 //  scoped_ptr_malloc added in by Google.  When one of
     18 //  these goes out of scope, instead of doing a delete or delete[], it
     19 //  calls free().  scoped_ptr_malloc<char> is likely to see much more
     20 //  use than any other specializations.
     21 
     22 //  release() added in by Google. Use this to conditionally
     23 //  transfer ownership of a heap-allocated object to the caller, usually on
     24 //  method success.
     25 #ifndef TALK_BASE_SCOPED_PTR_H__
     26 #define TALK_BASE_SCOPED_PTR_H__
     27 
     28 #include <cstddef>             // for std::ptrdiff_t
     29 #include <stdlib.h>            // for free() decl
     30 
     31 #include "talk/base/common.h"  // for ASSERT
     32 
     33 #ifdef _WIN32
     34 namespace std { using ::ptrdiff_t; };
     35 #endif // _WIN32
     36 
     37 namespace talk_base {
     38 
     39 template <typename T>
     40 class scoped_ptr {
     41  private:
     42 
     43   T* ptr;
     44 
     45   scoped_ptr(scoped_ptr const &);
     46   scoped_ptr & operator=(scoped_ptr const &);
     47 
     48  public:
     49 
     50   typedef T element_type;
     51 
     52   explicit scoped_ptr(T* p = NULL): ptr(p) {}
     53 
     54   ~scoped_ptr() {
     55     typedef char type_must_be_complete[sizeof(T)];
     56     delete ptr;
     57   }
     58 
     59   void reset(T* p = NULL) {
     60     typedef char type_must_be_complete[sizeof(T)];
     61 
     62     if (ptr != p) {
     63       T* obj = ptr;
     64       ptr = p;
     65       // Delete last, in case obj destructor indirectly results in ~scoped_ptr
     66       delete obj;
     67     }
     68   }
     69 
     70   T& operator*() const {
     71     ASSERT(ptr != NULL);
     72     return *ptr;
     73   }
     74 
     75   T* operator->() const  {
     76     ASSERT(ptr != NULL);
     77     return ptr;
     78   }
     79 
     80   T* get() const  {
     81     return ptr;
     82   }
     83 
     84   void swap(scoped_ptr & b) {
     85     T* tmp = b.ptr;
     86     b.ptr = ptr;
     87     ptr = tmp;
     88   }
     89 
     90   T* release() {
     91     T* tmp = ptr;
     92     ptr = NULL;
     93     return tmp;
     94   }
     95 
     96   T** accept() {
     97     if (ptr) {
     98       delete ptr;
     99       ptr = NULL;
    100     }
    101     return &ptr;
    102   }
    103 
    104   T** use() {
    105     return &ptr;
    106   }
    107 };
    108 
    109 template<typename T> inline
    110 void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) {
    111   a.swap(b);
    112 }
    113 
    114 
    115 
    116 
    117 //  scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
    118 //  is guaranteed, either on destruction of the scoped_array or via an explicit
    119 //  reset(). Use shared_array or std::vector if your needs are more complex.
    120 
    121 template<typename T>
    122 class scoped_array {
    123  private:
    124 
    125   T* ptr;
    126 
    127   scoped_array(scoped_array const &);
    128   scoped_array & operator=(scoped_array const &);
    129 
    130  public:
    131 
    132   typedef T element_type;
    133 
    134   explicit scoped_array(T* p = NULL) : ptr(p) {}
    135 
    136   ~scoped_array() {
    137     typedef char type_must_be_complete[sizeof(T)];
    138     delete[] ptr;
    139   }
    140 
    141   void reset(T* p = NULL) {
    142     typedef char type_must_be_complete[sizeof(T)];
    143 
    144     if (ptr != p) {
    145       T* arr = ptr;
    146       ptr = p;
    147       // Delete last, in case arr destructor indirectly results in ~scoped_array
    148       delete [] arr;
    149     }
    150   }
    151 
    152   T& operator[](std::ptrdiff_t i) const {
    153     ASSERT(ptr != NULL);
    154     ASSERT(i >= 0);
    155     return ptr[i];
    156   }
    157 
    158   T* get() const {
    159     return ptr;
    160   }
    161 
    162   void swap(scoped_array & b) {
    163     T* tmp = b.ptr;
    164     b.ptr = ptr;
    165     ptr = tmp;
    166   }
    167 
    168   T* release() {
    169     T* tmp = ptr;
    170     ptr = NULL;
    171     return tmp;
    172   }
    173 
    174   T** accept() {
    175     if (ptr) {
    176       delete [] ptr;
    177       ptr = NULL;
    178     }
    179     return &ptr;
    180   }
    181 };
    182 
    183 template<class T> inline
    184 void swap(scoped_array<T>& a, scoped_array<T>& b) {
    185   a.swap(b);
    186 }
    187 
    188 // scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
    189 // second template argument, the function used to free the object.
    190 
    191 template<typename T, void (*FF)(void*) = free> class scoped_ptr_malloc {
    192  private:
    193 
    194   T* ptr;
    195 
    196   scoped_ptr_malloc(scoped_ptr_malloc const &);
    197   scoped_ptr_malloc & operator=(scoped_ptr_malloc const &);
    198 
    199  public:
    200 
    201   typedef T element_type;
    202 
    203   explicit scoped_ptr_malloc(T* p = 0): ptr(p) {}
    204 
    205   ~scoped_ptr_malloc() {
    206     FF(static_cast<void*>(ptr));
    207   }
    208 
    209   void reset(T* p = 0) {
    210     if (ptr != p) {
    211       FF(static_cast<void*>(ptr));
    212       ptr = p;
    213     }
    214   }
    215 
    216   T& operator*() const {
    217     ASSERT(ptr != 0);
    218     return *ptr;
    219   }
    220 
    221   T* operator->() const {
    222     ASSERT(ptr != 0);
    223     return ptr;
    224   }
    225 
    226   T* get() const {
    227     return ptr;
    228   }
    229 
    230   void swap(scoped_ptr_malloc & b) {
    231     T* tmp = b.ptr;
    232     b.ptr = ptr;
    233     ptr = tmp;
    234   }
    235 
    236   T* release() {
    237     T* tmp = ptr;
    238     ptr = 0;
    239     return tmp;
    240   }
    241 
    242   T** accept() {
    243     if (ptr) {
    244       FF(static_cast<void*>(ptr));
    245       ptr = 0;
    246     }
    247     return &ptr;
    248   }
    249 };
    250 
    251 template<typename T, void (*FF)(void*)> inline
    252 void swap(scoped_ptr_malloc<T,FF>& a, scoped_ptr_malloc<T,FF>& b) {
    253   a.swap(b);
    254 }
    255 
    256 } // namespace talk_base
    257 
    258 #endif  // #ifndef TALK_BASE_SCOPED_PTR_H__
    259