• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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