Home | History | Annotate | Download | only in base
      1 // Copyright 2011 the V8 project 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 #ifndef V8_BASE_SMART_POINTERS_H_
      6 #define V8_BASE_SMART_POINTERS_H_
      7 
      8 #include "src/base/logging.h"
      9 
     10 namespace v8 {
     11 namespace base {
     12 
     13 template <typename Deallocator, typename T>
     14 class SmartPointerBase {
     15  public:
     16   // Default constructor. Constructs an empty scoped pointer.
     17   SmartPointerBase() : p_(NULL) {}
     18 
     19   // Constructs a scoped pointer from a plain one.
     20   explicit SmartPointerBase(T* ptr) : p_(ptr) {}
     21 
     22   // Copy constructor removes the pointer from the original to avoid double
     23   // freeing.
     24   SmartPointerBase(const SmartPointerBase<Deallocator, T>& rhs) : p_(rhs.p_) {
     25     const_cast<SmartPointerBase<Deallocator, T>&>(rhs).p_ = NULL;
     26   }
     27 
     28   T* operator->() const { return p_; }
     29 
     30   T& operator*() const { return *p_; }
     31 
     32   T* get() const { return p_; }
     33 
     34   // You can use [n] to index as if it was a plain pointer.
     35   T& operator[](size_t i) { return p_[i]; }
     36 
     37   // You can use [n] to index as if it was a plain pointer.
     38   const T& operator[](size_t i) const { return p_[i]; }
     39 
     40   // We don't have implicit conversion to a T* since that hinders migration:
     41   // You would not be able to change a method from returning a T* to
     42   // returning an SmartArrayPointer<T> and then get errors wherever it is used.
     43 
     44 
     45   // If you want to take out the plain pointer and don't want it automatically
     46   // deleted then call Detach().  Afterwards, the smart pointer is empty
     47   // (NULL).
     48   T* Detach() {
     49     T* temp = p_;
     50     p_ = NULL;
     51     return temp;
     52   }
     53 
     54   void Reset(T* new_value) {
     55     DCHECK(p_ == NULL || p_ != new_value);
     56     if (p_) Deallocator::Delete(p_);
     57     p_ = new_value;
     58   }
     59 
     60   // Assignment requires an empty (NULL) SmartArrayPointer as the receiver. Like
     61   // the copy constructor it removes the pointer in the original to avoid
     62   // double freeing.
     63   SmartPointerBase<Deallocator, T>& operator=(
     64       const SmartPointerBase<Deallocator, T>& rhs) {
     65     DCHECK(is_empty());
     66     T* tmp = rhs.p_;  // swap to handle self-assignment
     67     const_cast<SmartPointerBase<Deallocator, T>&>(rhs).p_ = NULL;
     68     p_ = tmp;
     69     return *this;
     70   }
     71 
     72   bool is_empty() const { return p_ == NULL; }
     73 
     74  protected:
     75   // When the destructor of the scoped pointer is executed the plain pointer
     76   // is deleted using DeleteArray.  This implies that you must allocate with
     77   // NewArray.
     78   ~SmartPointerBase() {
     79     if (p_) Deallocator::Delete(p_);
     80   }
     81 
     82  private:
     83   T* p_;
     84 };
     85 
     86 // A 'scoped array pointer' that calls DeleteArray on its pointer when the
     87 // destructor is called.
     88 
     89 template <typename T>
     90 struct ArrayDeallocator {
     91   static void Delete(T* array) { delete[] array; }
     92 };
     93 
     94 
     95 template <typename T>
     96 class SmartArrayPointer : public SmartPointerBase<ArrayDeallocator<T>, T> {
     97  public:
     98   SmartArrayPointer() {}
     99   explicit SmartArrayPointer(T* ptr)
    100       : SmartPointerBase<ArrayDeallocator<T>, T>(ptr) {}
    101   SmartArrayPointer(const SmartArrayPointer<T>& rhs)
    102       : SmartPointerBase<ArrayDeallocator<T>, T>(rhs) {}
    103 };
    104 
    105 
    106 template <typename T>
    107 struct ObjectDeallocator {
    108   static void Delete(T* object) { delete object; }
    109 };
    110 
    111 template <typename T>
    112 class SmartPointer : public SmartPointerBase<ObjectDeallocator<T>, T> {
    113  public:
    114   SmartPointer() {}
    115   explicit SmartPointer(T* ptr)
    116       : SmartPointerBase<ObjectDeallocator<T>, T>(ptr) {}
    117   SmartPointer(const SmartPointer<T>& rhs)
    118       : SmartPointerBase<ObjectDeallocator<T>, T>(rhs) {}
    119 };
    120 
    121 }  // namespace base
    122 }  // namespace v8
    123 
    124 #endif  // V8_SMART_POINTERS_H_
    125