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