blob: 02025bb7960b436bd41c8e85622dfebd251e30ee [file] [log] [blame]
kmillikin@chromium.org83e16822011-09-13 08:21:47 +00001// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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
yangguo@chromium.org304cc332012-07-24 07:59:48 +000028#ifndef V8_SMART_POINTERS_H_
29#define V8_SMART_POINTERS_H_
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000030
kasperl@chromium.org71affb52009-05-26 05:44:31 +000031namespace v8 {
32namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000033
34
yangguo@chromium.org304cc332012-07-24 07:59:48 +000035template<typename Deallocator, typename T>
36class SmartPointerBase {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037 public:
ricow@chromium.org55ee8072011-09-08 16:33:10 +000038 // Default constructor. Constructs an empty scoped pointer.
yangguo@chromium.org304cc332012-07-24 07:59:48 +000039 inline SmartPointerBase() : p_(NULL) {}
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000040
ricow@chromium.org55ee8072011-09-08 16:33:10 +000041 // Constructs a scoped pointer from a plain one.
yangguo@chromium.org304cc332012-07-24 07:59:48 +000042 explicit inline SmartPointerBase(T* ptr) : p_(ptr) {}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000043
44 // Copy constructor removes the pointer from the original to avoid double
45 // freeing.
yangguo@chromium.org304cc332012-07-24 07:59:48 +000046 inline SmartPointerBase(const SmartPointerBase<Deallocator, T>& rhs)
47 : p_(rhs.p_) {
48 const_cast<SmartPointerBase<Deallocator, T>&>(rhs).p_ = NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000049 }
50
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000051 // 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.
yangguo@chromium.org304cc332012-07-24 07:59:48 +000054 inline ~SmartPointerBase() { if (p_) Deallocator::Delete(p_); }
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000055
ricow@chromium.org55ee8072011-09-08 16:33:10 +000056 inline T* operator->() const { return p_; }
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000057
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000058 // You can get the underlying pointer out with the * operator.
ricow@chromium.org55ee8072011-09-08 16:33:10 +000059 inline T* operator*() { return p_; }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000060
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000061 // You can use [n] to index as if it was a plain pointer.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000062 inline T& operator[](size_t i) {
ricow@chromium.org55ee8072011-09-08 16:33:10 +000063 return p_[i];
kasperl@chromium.orgb9123622008-09-17 14:05:56 +000064 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000065
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000066 // 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
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000071 // 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
kmillikin@chromium.org83e16822011-09-13 08:21:47 +000073 // returning an SmartArrayPointer<T> and then get errors wherever it is used.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000074
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() {
ricow@chromium.org55ee8072011-09-08 16:33:10 +000080 T* temp = p_;
81 p_ = NULL;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000082 return temp;
83 }
84
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +000085 inline void Reset(T* new_value) {
86 if (p_) Deallocator::Delete(p_);
87 p_ = new_value;
88 }
89
kmillikin@chromium.org83e16822011-09-13 08:21:47 +000090 // Assignment requires an empty (NULL) SmartArrayPointer as the receiver. Like
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000091 // the copy constructor it removes the pointer in the original to avoid
92 // double freeing.
yangguo@chromium.org304cc332012-07-24 07:59:48 +000093 inline SmartPointerBase<Deallocator, T>& operator=(
94 const SmartPointerBase<Deallocator, T>& rhs) {
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +000095 ASSERT(is_empty());
ricow@chromium.org55ee8072011-09-08 16:33:10 +000096 T* tmp = rhs.p_; // swap to handle self-assignment
yangguo@chromium.org304cc332012-07-24 07:59:48 +000097 const_cast<SmartPointerBase<Deallocator, T>&>(rhs).p_ = NULL;
ricow@chromium.org55ee8072011-09-08 16:33:10 +000098 p_ = tmp;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000099 return *this;
100 }
101
ricow@chromium.org55ee8072011-09-08 16:33:10 +0000102 inline bool is_empty() { return p_ == NULL; }
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000103
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000104 private:
ricow@chromium.org55ee8072011-09-08 16:33:10 +0000105 T* p_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000106};
107
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000108// 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* array) {
133 Malloced::Delete(array);
134 }
135};
136
137template<typename T>
138class SmartPointer: public SmartPointerBase<ObjectDeallocator<T>, T> {
139 public:
140 inline SmartPointer() { }
141 explicit inline SmartPointer(T* ptr)
142 : SmartPointerBase<ObjectDeallocator<T>, T>(ptr) { }
143 inline SmartPointer(const SmartPointer<T>& rhs)
144 : SmartPointerBase<ObjectDeallocator<T>, T>(rhs) { }
145};
146
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000147} } // namespace v8::internal
148
yangguo@chromium.org304cc332012-07-24 07:59:48 +0000149#endif // V8_SMART_POINTERS_H_