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. SmartPointerBase()17 SmartPointerBase() : p_(NULL) {} 18 19 // Constructs a scoped pointer from a plain one. SmartPointerBase(T * ptr)20 explicit SmartPointerBase(T* ptr) : p_(ptr) {} 21 22 // Copy constructor removes the pointer from the original to avoid double 23 // freeing. SmartPointerBase(const SmartPointerBase<Deallocator,T> & rhs)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 get()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). Detach()48 T* Detach() { 49 T* temp = p_; 50 p_ = NULL; 51 return temp; 52 } 53 Reset(T * new_value)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 is_empty()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. ~SmartPointerBase()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 { DeleteArrayDeallocator91 static void Delete(T* array) { delete[] array; } 92 }; 93 94 95 template <typename T> 96 class SmartArrayPointer : public SmartPointerBase<ArrayDeallocator<T>, T> { 97 public: SmartArrayPointer()98 SmartArrayPointer() {} SmartArrayPointer(T * ptr)99 explicit SmartArrayPointer(T* ptr) 100 : SmartPointerBase<ArrayDeallocator<T>, T>(ptr) {} SmartArrayPointer(const SmartArrayPointer<T> & rhs)101 SmartArrayPointer(const SmartArrayPointer<T>& rhs) 102 : SmartPointerBase<ArrayDeallocator<T>, T>(rhs) {} 103 }; 104 105 106 template <typename T> 107 struct ObjectDeallocator { DeleteObjectDeallocator108 static void Delete(T* object) { delete object; } 109 }; 110 111 template <typename T> 112 class SmartPointer : public SmartPointerBase<ObjectDeallocator<T>, T> { 113 public: SmartPointer()114 SmartPointer() {} SmartPointer(T * ptr)115 explicit SmartPointer(T* ptr) 116 : SmartPointerBase<ObjectDeallocator<T>, T>(ptr) {} SmartPointer(const SmartPointer<T> & rhs)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