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