1 /*
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 #include "JNIHelp.h"  // For DISALLOW_COPY_AND_ASSIGN.
22 
23 // Default deleter for pointer types.
24 template <typename T>
25 struct DefaultDelete {
26     enum { type_must_be_complete = sizeof(T) };
DefaultDeleteDefaultDelete27     DefaultDelete() {}
operatorDefaultDelete28     void operator()(T* p) const {
29         delete p;
30     }
31 };
32 
33 // Default deleter for array types.
34 template <typename T>
35 struct 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);
50 template <typename T, typename D = DefaultDelete<T> >
51 class UniquePtr {
52 public:
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 
84 private:
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 
92     DISALLOW_COPY_AND_ASSIGN(UniquePtr);
93 };
94 
95 // Partial specialization for array types. Like std::unique_ptr, this removes
96 // operator* and operator-> but adds operator[].
97 template <typename T, typename D>
98 class UniquePtr<T[], D> {
99 public:
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 
125 private:
126     T* mPtr;
127 
128     DISALLOW_COPY_AND_ASSIGN(UniquePtr);
129 };
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 
138 static void assert(bool b) {
139     if (!b) {
140         fprintf(stderr, "FAIL\n");
141         abort();
142     }
143     fprintf(stderr, "OK\n");
144 }
145 static int cCount = 0;
146 struct C {
147     C() { ++cCount; }
148     ~C() { --cCount; }
149 };
150 static bool freed = false;
151 struct Freer {
152     void operator()(int* p) {
153         assert(*p == 123);
154         free(p);
155         freed = true;
156     }
157 };
158 
159 int 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
229