Home | History | Annotate | Download | only in internal
      1 // Ceres Solver - A fast non-linear least squares minimizer
      2 // Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
      3 // http://code.google.com/p/ceres-solver/
      4 //
      5 // Redistribution and use in source and binary forms, with or without
      6 // modification, are permitted provided that the following conditions are met:
      7 //
      8 // * Redistributions of source code must retain the above copyright notice,
      9 //   this list of conditions and the following disclaimer.
     10 // * Redistributions in binary form must reproduce the above copyright notice,
     11 //   this list of conditions and the following disclaimer in the documentation
     12 //   and/or other materials provided with the distribution.
     13 // * Neither the name of Google Inc. nor the names of its contributors may be
     14 //   used to endorse or promote products derived from this software without
     15 //   specific prior written permission.
     16 //
     17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27 // POSSIBILITY OF SUCH DAMAGE.
     28 //
     29 // Author: jorg (at) google.com (Jorg Brown)
     30 //
     31 // This is an implementation designed to match the anticipated future TR2
     32 // implementation of the scoped_ptr class, and its closely-related brethren,
     33 // scoped_array, scoped_ptr_malloc, and make_scoped_ptr.
     34 
     35 #ifndef CERES_PUBLIC_INTERNAL_SCOPED_PTR_H_
     36 #define CERES_PUBLIC_INTERNAL_SCOPED_PTR_H_
     37 
     38 #include <assert.h>
     39 #include <stdlib.h>
     40 #include <cstddef>
     41 #include <algorithm>
     42 
     43 namespace ceres {
     44 namespace internal {
     45 
     46 template <class C> class scoped_ptr;
     47 template <class C, class Free> class scoped_ptr_malloc;
     48 template <class C> class scoped_array;
     49 
     50 template <class C>
     51 scoped_ptr<C> make_scoped_ptr(C *);
     52 
     53 // A scoped_ptr<T> is like a T*, except that the destructor of
     54 // scoped_ptr<T> automatically deletes the pointer it holds (if
     55 // any). That is, scoped_ptr<T> owns the T object that it points
     56 // to. Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to
     57 // a T object. Also like T*, scoped_ptr<T> is thread-compatible, and
     58 // once you dereference it, you get the threadsafety guarantees of T.
     59 //
     60 // The size of a scoped_ptr is small: sizeof(scoped_ptr<C>) == sizeof(C*)
     61 template <class C>
     62 class scoped_ptr {
     63  public:
     64   // The element type
     65   typedef C element_type;
     66 
     67   // Constructor.  Defaults to intializing with NULL.
     68   // There is no way to create an uninitialized scoped_ptr.
     69   // The input parameter must be allocated with new.
     70   explicit scoped_ptr(C* p = NULL) : ptr_(p) { }
     71 
     72   // Destructor.  If there is a C object, delete it.
     73   // We don't need to test ptr_ == NULL because C++ does that for us.
     74   ~scoped_ptr() {
     75     enum { type_must_be_complete = sizeof(C) };
     76     delete ptr_;
     77   }
     78 
     79   // Reset.  Deletes the current owned object, if any.
     80   // Then takes ownership of a new object, if given.
     81   // this->reset(this->get()) works.
     82   void reset(C* p = NULL) {
     83     if (p != ptr_) {
     84       enum { type_must_be_complete = sizeof(C) };
     85       delete ptr_;
     86       ptr_ = p;
     87     }
     88   }
     89 
     90   // Accessors to get the owned object.
     91   // operator* and operator-> will assert() if there is no current object.
     92   C& operator*() const {
     93     assert(ptr_ != NULL);
     94     return *ptr_;
     95   }
     96   C* operator->() const  {
     97     assert(ptr_ != NULL);
     98     return ptr_;
     99   }
    100   C* get() const { return ptr_; }
    101 
    102   // Comparison operators.
    103   // These return whether a scoped_ptr and a raw pointer refer to
    104   // the same object, not just to two different but equal objects.
    105   bool operator==(const C* p) const { return ptr_ == p; }
    106   bool operator!=(const C* p) const { return ptr_ != p; }
    107 
    108   // Swap two scoped pointers.
    109   void swap(scoped_ptr& p2) {
    110     C* tmp = ptr_;
    111     ptr_ = p2.ptr_;
    112     p2.ptr_ = tmp;
    113   }
    114 
    115   // Release a pointer.
    116   // The return value is the current pointer held by this object.
    117   // If this object holds a NULL pointer, the return value is NULL.
    118   // After this operation, this object will hold a NULL pointer,
    119   // and will not own the object any more.
    120   C* release() {
    121     C* retVal = ptr_;
    122     ptr_ = NULL;
    123     return retVal;
    124   }
    125 
    126  private:
    127   C* ptr_;
    128 
    129   // google3 friend class that can access copy ctor (although if it actually
    130   // calls a copy ctor, there will be a problem) see below
    131   friend scoped_ptr<C> make_scoped_ptr<C>(C *p);
    132 
    133   // Forbid comparison of scoped_ptr types.  If C2 != C, it totally doesn't
    134   // make sense, and if C2 == C, it still doesn't make sense because you should
    135   // never have the same object owned by two different scoped_ptrs.
    136   template <class C2> bool operator==(scoped_ptr<C2> const& p2) const;
    137   template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const;
    138 
    139   // Disallow evil constructors
    140   scoped_ptr(const scoped_ptr&);
    141   void operator=(const scoped_ptr&);
    142 };
    143 
    144 // Free functions
    145 template <class C>
    146 inline void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) {
    147   p1.swap(p2);
    148 }
    149 
    150 template <class C>
    151 inline bool operator==(const C* p1, const scoped_ptr<C>& p2) {
    152   return p1 == p2.get();
    153 }
    154 
    155 template <class C>
    156 inline bool operator==(const C* p1, const scoped_ptr<const C>& p2) {
    157   return p1 == p2.get();
    158 }
    159 
    160 template <class C>
    161 inline bool operator!=(const C* p1, const scoped_ptr<C>& p2) {
    162   return p1 != p2.get();
    163 }
    164 
    165 template <class C>
    166 inline bool operator!=(const C* p1, const scoped_ptr<const C>& p2) {
    167   return p1 != p2.get();
    168 }
    169 
    170 template <class C>
    171 scoped_ptr<C> make_scoped_ptr(C *p) {
    172   // This does nothing but to return a scoped_ptr of the type that the passed
    173   // pointer is of.  (This eliminates the need to specify the name of T when
    174   // making a scoped_ptr that is used anonymously/temporarily.)  From an
    175   // access control point of view, we construct an unnamed scoped_ptr here
    176   // which we return and thus copy-construct.  Hence, we need to have access
    177   // to scoped_ptr::scoped_ptr(scoped_ptr const &).  However, it is guaranteed
    178   // that we never actually call the copy constructor, which is a good thing
    179   // as we would call the temporary's object destructor (and thus delete p)
    180   // if we actually did copy some object, here.
    181   return scoped_ptr<C>(p);
    182 }
    183 
    184 // scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
    185 // with new [] and the destructor deletes objects with delete [].
    186 //
    187 // As with scoped_ptr<C>, a scoped_array<C> either points to an object
    188 // or is NULL.  A scoped_array<C> owns the object that it points to.
    189 // scoped_array<T> is thread-compatible, and once you index into it,
    190 // the returned objects have only the threadsafety guarantees of T.
    191 //
    192 // Size: sizeof(scoped_array<C>) == sizeof(C*)
    193 template <class C>
    194 class scoped_array {
    195  public:
    196   // The element type
    197   typedef C element_type;
    198 
    199   // Constructor.  Defaults to intializing with NULL.
    200   // There is no way to create an uninitialized scoped_array.
    201   // The input parameter must be allocated with new [].
    202   explicit scoped_array(C* p = NULL) : array_(p) { }
    203 
    204   // Destructor.  If there is a C object, delete it.
    205   // We don't need to test ptr_ == NULL because C++ does that for us.
    206   ~scoped_array() {
    207     enum { type_must_be_complete = sizeof(C) };
    208     delete[] array_;
    209   }
    210 
    211   // Reset. Deletes the current owned object, if any.
    212   // Then takes ownership of a new object, if given.
    213   // this->reset(this->get()) works.
    214   void reset(C* p = NULL) {
    215     if (p != array_) {
    216       enum { type_must_be_complete = sizeof(C) };
    217       delete[] array_;
    218       array_ = p;
    219     }
    220   }
    221 
    222   // Get one element of the current object.
    223   // Will assert() if there is no current object, or index i is negative.
    224   C& operator[](std::ptrdiff_t i) const {
    225     assert(i >= 0);
    226     assert(array_ != NULL);
    227     return array_[i];
    228   }
    229 
    230   // Get a pointer to the zeroth element of the current object.
    231   // If there is no current object, return NULL.
    232   C* get() const {
    233     return array_;
    234   }
    235 
    236   // Comparison operators.
    237   // These return whether a scoped_array and a raw pointer refer to
    238   // the same array, not just to two different but equal arrays.
    239   bool operator==(const C* p) const { return array_ == p; }
    240   bool operator!=(const C* p) const { return array_ != p; }
    241 
    242   // Swap two scoped arrays.
    243   void swap(scoped_array& p2) {
    244     C* tmp = array_;
    245     array_ = p2.array_;
    246     p2.array_ = tmp;
    247   }
    248 
    249   // Release an array.
    250   // The return value is the current pointer held by this object.
    251   // If this object holds a NULL pointer, the return value is NULL.
    252   // After this operation, this object will hold a NULL pointer,
    253   // and will not own the object any more.
    254   C* release() {
    255     C* retVal = array_;
    256     array_ = NULL;
    257     return retVal;
    258   }
    259 
    260  private:
    261   C* array_;
    262 
    263   // Forbid comparison of different scoped_array types.
    264   template <class C2> bool operator==(scoped_array<C2> const& p2) const;
    265   template <class C2> bool operator!=(scoped_array<C2> const& p2) const;
    266 
    267   // Disallow evil constructors
    268   scoped_array(const scoped_array&);
    269   void operator=(const scoped_array&);
    270 };
    271 
    272 // Free functions
    273 template <class C>
    274 inline void swap(scoped_array<C>& p1, scoped_array<C>& p2) {
    275   p1.swap(p2);
    276 }
    277 
    278 template <class C>
    279 inline bool operator==(const C* p1, const scoped_array<C>& p2) {
    280   return p1 == p2.get();
    281 }
    282 
    283 template <class C>
    284 inline bool operator==(const C* p1, const scoped_array<const C>& p2) {
    285   return p1 == p2.get();
    286 }
    287 
    288 template <class C>
    289 inline bool operator!=(const C* p1, const scoped_array<C>& p2) {
    290   return p1 != p2.get();
    291 }
    292 
    293 template <class C>
    294 inline bool operator!=(const C* p1, const scoped_array<const C>& p2) {
    295   return p1 != p2.get();
    296 }
    297 
    298 // This class wraps the c library function free() in a class that can be
    299 // passed as a template argument to scoped_ptr_malloc below.
    300 class ScopedPtrMallocFree {
    301  public:
    302   inline void operator()(void* x) const {
    303     free(x);
    304   }
    305 };
    306 
    307 }  // namespace internal
    308 }  // namespace ceres
    309 
    310 #endif  // CERES_PUBLIC_INTERNAL_SCOPED_PTR_H_
    311