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