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