1// Copyright 2011 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28#ifndef V8_SMART_POINTERS_H_ 29#define V8_SMART_POINTERS_H_ 30 31namespace v8 { 32namespace internal { 33 34 35template<typename Deallocator, typename T> 36class SmartPointerBase { 37 public: 38 // Default constructor. Constructs an empty scoped pointer. 39 inline SmartPointerBase() : p_(NULL) {} 40 41 // Constructs a scoped pointer from a plain one. 42 explicit inline SmartPointerBase(T* ptr) : p_(ptr) {} 43 44 // Copy constructor removes the pointer from the original to avoid double 45 // freeing. 46 inline SmartPointerBase(const SmartPointerBase<Deallocator, T>& rhs) 47 : p_(rhs.p_) { 48 const_cast<SmartPointerBase<Deallocator, T>&>(rhs).p_ = NULL; 49 } 50 51 // When the destructor of the scoped pointer is executed the plain pointer 52 // is deleted using DeleteArray. This implies that you must allocate with 53 // NewArray. 54 inline ~SmartPointerBase() { if (p_) Deallocator::Delete(p_); } 55 56 inline T* operator->() const { return p_; } 57 58 // You can get the underlying pointer out with the * operator. 59 inline T* operator*() { return p_; } 60 61 // You can use [n] to index as if it was a plain pointer. 62 inline T& operator[](size_t i) { 63 return p_[i]; 64 } 65 66 // You can use [n] to index as if it was a plain pointer. 67 const inline T& operator[](size_t i) const { 68 return p_[i]; 69 } 70 71 // We don't have implicit conversion to a T* since that hinders migration: 72 // You would not be able to change a method from returning a T* to 73 // returning an SmartArrayPointer<T> and then get errors wherever it is used. 74 75 76 // If you want to take out the plain pointer and don't want it automatically 77 // deleted then call Detach(). Afterwards, the smart pointer is empty 78 // (NULL). 79 inline T* Detach() { 80 T* temp = p_; 81 p_ = NULL; 82 return temp; 83 } 84 85 inline void Reset(T* new_value) { 86 if (p_) Deallocator::Delete(p_); 87 p_ = new_value; 88 } 89 90 // Assignment requires an empty (NULL) SmartArrayPointer as the receiver. Like 91 // the copy constructor it removes the pointer in the original to avoid 92 // double freeing. 93 inline SmartPointerBase<Deallocator, T>& operator=( 94 const SmartPointerBase<Deallocator, T>& rhs) { 95 ASSERT(is_empty()); 96 T* tmp = rhs.p_; // swap to handle self-assignment 97 const_cast<SmartPointerBase<Deallocator, T>&>(rhs).p_ = NULL; 98 p_ = tmp; 99 return *this; 100 } 101 102 inline bool is_empty() { return p_ == NULL; } 103 104 private: 105 T* p_; 106}; 107 108// A 'scoped array pointer' that calls DeleteArray on its pointer when the 109// destructor is called. 110 111template<typename T> 112struct ArrayDeallocator { 113 static void Delete(T* array) { 114 DeleteArray(array); 115 } 116}; 117 118 119template<typename T> 120class SmartArrayPointer: public SmartPointerBase<ArrayDeallocator<T>, T> { 121 public: 122 inline SmartArrayPointer() { } 123 explicit inline SmartArrayPointer(T* ptr) 124 : SmartPointerBase<ArrayDeallocator<T>, T>(ptr) { } 125 inline SmartArrayPointer(const SmartArrayPointer<T>& rhs) 126 : SmartPointerBase<ArrayDeallocator<T>, T>(rhs) { } 127}; 128 129 130template<typename T> 131struct ObjectDeallocator { 132 static void Delete(T* object) { 133 delete object; 134 } 135}; 136 137 138template<typename T> 139class SmartPointer: public SmartPointerBase<ObjectDeallocator<T>, T> { 140 public: 141 inline SmartPointer() { } 142 explicit inline SmartPointer(T* ptr) 143 : SmartPointerBase<ObjectDeallocator<T>, T>(ptr) { } 144 inline SmartPointer(const SmartPointer<T>& rhs) 145 : SmartPointerBase<ObjectDeallocator<T>, T>(rhs) { } 146}; 147 148} } // namespace v8::internal 149 150#endif // V8_SMART_POINTERS_H_ 151