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