/ src / common / scoped_ptr.h
scoped_ptr.h
  1  // Copyright 2013 Google LLC
  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 LLC 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_