blob: 50f75b2b0cbeb19a456bd0603771e481677f5b80 [file] [log] [blame]
Brian Carlstrom3d9d2142013-05-10 14:09:30 -07001/*
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
Kenny Rootc4c83a72013-09-11 14:21:26 -070022// This is a fake declaration of std::swap to avoid including <algorithm>
23namespace std {
24template <class T> void swap(T&, T&);
25}
26
Brian Carlstrom3d9d2142013-05-10 14:09:30 -070027// Default deleter for pointer types.
28template <typename T>
29struct DefaultDelete {
30 enum { type_must_be_complete = sizeof(T) };
31 DefaultDelete() {}
32 void operator()(T* p) const {
33 delete p;
34 }
35};
36
37// Default deleter for array types.
38template <typename T>
39struct DefaultDelete<T[]> {
40 enum { type_must_be_complete = sizeof(T) };
41 void operator()(T* p) const {
42 delete[] p;
43 }
44};
45
46// A smart pointer that deletes the given pointer on destruction.
47// Equivalent to C++0x's std::unique_ptr (a combination of boost::scoped_ptr
48// and boost::scoped_array).
49// Named to be in keeping with Android style but also to avoid
50// collision with any other implementation, until we can switch over
51// to unique_ptr.
52// Use thus:
53// UniquePtr<C> c(new C);
54template <typename T, typename D = DefaultDelete<T> >
55class UniquePtr {
56public:
57 // Construct a new UniquePtr, taking ownership of the given raw pointer.
58 explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
59 }
60
61 ~UniquePtr() {
62 reset();
63 }
64
65 // Accessors.
66 T& operator*() const { return *mPtr; }
67 T* operator->() const { return mPtr; }
68 T* get() const { return mPtr; }
69
70 // Returns the raw pointer and hands over ownership to the caller.
71 // The pointer will not be deleted by UniquePtr.
72 T* release() __attribute__((warn_unused_result)) {
73 T* result = mPtr;
74 mPtr = NULL;
75 return result;
76 }
77
78 // Takes ownership of the given raw pointer.
79 // If this smart pointer previously owned a different raw pointer, that
80 // raw pointer will be freed.
81 void reset(T* ptr = NULL) {
82 if (ptr != mPtr) {
83 D()(mPtr);
84 mPtr = ptr;
85 }
86 }
87
Mathieu Chartier7cc37bb2012-11-09 15:45:15 -080088 // Swap with another unique pointer.
89 void swap(UniquePtr<T>& other) {
90 std::swap(mPtr, other.mPtr);
91 }
92
Brian Carlstrom3d9d2142013-05-10 14:09:30 -070093private:
94 // The raw pointer.
95 T* mPtr;
96
97 // Comparing unique pointers is probably a mistake, since they're unique.
98 template <typename T2> bool operator==(const UniquePtr<T2>& p) const;
99 template <typename T2> bool operator!=(const UniquePtr<T2>& p) const;
100
101 // Disallow copy and assignment.
102 UniquePtr(const UniquePtr&);
103 void operator=(const UniquePtr&);
104};
105
106// Partial specialization for array types. Like std::unique_ptr, this removes
107// operator* and operator-> but adds operator[].
108template <typename T, typename D>
109class UniquePtr<T[], D> {
110public:
111 explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
112 }
113
114 ~UniquePtr() {
115 reset();
116 }
117
118 T& operator[](size_t i) const {
119 return mPtr[i];
120 }
121 T* get() const { return mPtr; }
122
123 T* release() __attribute__((warn_unused_result)) {
124 T* result = mPtr;
125 mPtr = NULL;
126 return result;
127 }
128
129 void reset(T* ptr = NULL) {
130 if (ptr != mPtr) {
131 D()(mPtr);
132 mPtr = ptr;
133 }
134 }
135
136private:
137 T* mPtr;
138
139 // Disallow copy and assignment.
140 UniquePtr(const UniquePtr&);
141 void operator=(const UniquePtr&);
142};
143
144#if UNIQUE_PTR_TESTS
145
146// Run these tests with:
147// g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out
148
149#include <stdio.h>
150
151static void assert(bool b) {
152 if (!b) {
153 fprintf(stderr, "FAIL\n");
154 abort();
155 }
156 fprintf(stderr, "OK\n");
157}
158static int cCount = 0;
159struct C {
160 C() { ++cCount; }
161 ~C() { --cCount; }
162};
163static bool freed = false;
164struct Freer {
165 void operator()(int* p) {
166 assert(*p == 123);
167 free(p);
168 freed = true;
169 }
170};
171
172int main(int argc, char* argv[]) {
173 //
174 // UniquePtr<T> tests...
175 //
176
177 // Can we free a single object?
178 {
179 UniquePtr<C> c(new C);
180 assert(cCount == 1);
181 }
182 assert(cCount == 0);
183 // Does release work?
184 C* rawC;
185 {
186 UniquePtr<C> c(new C);
187 assert(cCount == 1);
188 rawC = c.release();
189 }
190 assert(cCount == 1);
191 delete rawC;
192 // Does reset work?
193 {
194 UniquePtr<C> c(new C);
195 assert(cCount == 1);
196 c.reset(new C);
197 assert(cCount == 1);
198 }
199 assert(cCount == 0);
200
201 //
202 // UniquePtr<T[]> tests...
203 //
204
205 // Can we free an array?
206 {
207 UniquePtr<C[]> cs(new C[4]);
208 assert(cCount == 4);
209 }
210 assert(cCount == 0);
211 // Does release work?
212 {
213 UniquePtr<C[]> c(new C[4]);
214 assert(cCount == 4);
215 rawC = c.release();
216 }
217 assert(cCount == 4);
218 delete[] rawC;
219 // Does reset work?
220 {
221 UniquePtr<C[]> c(new C[4]);
222 assert(cCount == 4);
223 c.reset(new C[2]);
224 assert(cCount == 2);
225 }
226 assert(cCount == 0);
227
228 //
229 // Custom deleter tests...
230 //
231 assert(!freed);
232 {
233 UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int))));
234 *i = 123;
235 }
236 assert(freed);
237 return 0;
238}
239#endif
240
241#endif // UNIQUE_PTR_H_included