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