blob: f5c7c2ca35676482a5cd15c4ffbc6a6d5cdfc08f [file] [log] [blame]
Elliott Hughesc015c1b2010-02-02 18:24:57 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef UNIQUE_PTR_H_included
18#define UNIQUE_PTR_H_included
19
20#include <cstdlib> // For NULL.
21
22// Default deleter for pointer types.
23template <typename T>
24struct DefaultDelete {
25 enum { type_must_be_complete = sizeof(T) };
26 DefaultDelete() {}
27 void operator()(T* p) const {
28 delete p;
29 }
30};
31
32// Default deleter for array types.
33template <typename T>
34struct DefaultDelete<T[]> {
35 enum { type_must_be_complete = sizeof(T) };
36 void operator()(T* p) const {
37 delete[] p;
38 }
39};
40
41// A smart pointer that deletes the given pointer on destruction.
42// Equivalent to C++0x's std::unique_ptr (a combination of boost::scoped_ptr
43// and boost::scoped_array).
44// Named to be in keeping with Android style but also to avoid
45// collision with any other implementation, until we can switch over
46// to unique_ptr.
47// Use thus:
48// UniquePtr<C> c(new C);
49template <typename T, typename D = DefaultDelete<T> >
50class UniquePtr {
51public:
52 // Construct a new UniquePtr, taking ownership of the given raw pointer.
53 explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
54 }
55
56 ~UniquePtr() {
57 reset();
58 }
59
60 // Accessors.
61 T& operator*() const { return *mPtr; }
62 T* operator->() const { return mPtr; }
63 T* get() const { return mPtr; }
64
65 // Returns the raw pointer and hands over ownership to the caller.
66 // The pointer will not be deleted by UniquePtr.
67 T* release() {
68 T* result = mPtr;
69 mPtr = NULL;
70 return result;
71 }
72
73 // Takes ownership of the given raw pointer.
74 // If this smart pointer previously owned a different raw pointer, that
75 // raw pointer will be freed.
76 void reset(T* ptr = NULL) {
77 if (ptr != mPtr) {
78 D()(mPtr);
79 mPtr = ptr;
80 }
81 }
82
83private:
84 // The raw pointer.
85 T* mPtr;
86
87 // Comparing unique pointers is probably a mistake, since they're unique.
88 template <typename T2> bool operator==(const UniquePtr<T2>& p) const;
89 template <typename T2> bool operator!=(const UniquePtr<T2>& p) const;
90
91 // Disallow copy and assignment.
92 UniquePtr(const UniquePtr&);
93 void operator=(const UniquePtr&);
94};
95
96// Partial specialization for array types. Like std::unique_ptr, this removes
97// operator* and operator-> but adds operator[].
98template <typename T, typename D>
99class UniquePtr<T[], D> {
100public:
101 explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
102 }
103
104 ~UniquePtr() {
105 reset();
106 }
107
108 T& operator[](size_t i) const {
109 return mPtr[i];
110 }
111 T* get() const { return mPtr; }
112
113 T* release() {
114 T* result = mPtr;
115 mPtr = NULL;
116 return result;
117 }
118
119 void reset(T* ptr = NULL) {
120 if (ptr != mPtr) {
121 D()(mPtr);
122 mPtr = ptr;
123 }
124 }
125
126private:
127 T* mPtr;
128
129 // Disallow copy and assignment.
130 UniquePtr(const UniquePtr&);
131 void operator=(const UniquePtr&);
132};
133
134#if UNIQUE_PTR_TESTS
135
136// Run these tests with:
137// g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out
138
139#include <stdio.h>
140
141static void assert(bool b) {
142 if (!b) {
143 fprintf(stderr, "FAIL\n");
144 abort();
145 }
146 fprintf(stderr, "OK\n");
147}
148static int cCount = 0;
149struct C {
150 C() { ++cCount; }
151 ~C() { --cCount; }
152};
153static bool freed = false;
154struct Freer {
155 void operator()(int* p) {
156 assert(*p == 123);
157 free(p);
158 freed = true;
159 }
160};
161
162int main(int argc, char* argv[]) {
163 //
164 // UniquePtr<T> tests...
165 //
166
167 // Can we free a single object?
168 {
169 UniquePtr<C> c(new C);
170 assert(cCount == 1);
171 }
172 assert(cCount == 0);
173 // Does release work?
174 C* rawC;
175 {
176 UniquePtr<C> c(new C);
177 assert(cCount == 1);
178 rawC = c.release();
179 }
180 assert(cCount == 1);
181 delete rawC;
182 // Does reset work?
183 {
184 UniquePtr<C> c(new C);
185 assert(cCount == 1);
186 c.reset(new C);
187 assert(cCount == 1);
188 }
189 assert(cCount == 0);
190
191 //
192 // UniquePtr<T[]> tests...
193 //
194
195 // Can we free an array?
196 {
197 UniquePtr<C[]> cs(new C[4]);
198 assert(cCount == 4);
199 }
200 assert(cCount == 0);
201 // Does release work?
202 {
203 UniquePtr<C[]> c(new C[4]);
204 assert(cCount == 4);
205 rawC = c.release();
206 }
207 assert(cCount == 4);
208 delete[] rawC;
209 // Does reset work?
210 {
211 UniquePtr<C[]> c(new C[4]);
212 assert(cCount == 4);
213 c.reset(new C[2]);
214 assert(cCount == 2);
215 }
216 assert(cCount == 0);
217
218 //
219 // Custom deleter tests...
220 //
221 assert(!freed);
222 {
223 UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int))));
224 *i = 123;
225 }
226 assert(freed);
227 return 0;
228}
229#endif
230
231#endif // UNIQUE_PTR_H_included