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