• 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 public:
54     // Construct a new UniquePtr, taking ownership of the given raw pointer.
55     explicit UniquePtr(T* ptr = nullptr) : mPtr(ptr) {
56     }
57 
58     ~UniquePtr() {
59         reset();
60     }
61 
62     // Accessors.
63     T& operator*() const { return *mPtr; }
64     T* operator->() const { return mPtr; }
65     T* get() const { return mPtr; }
66 
67     // Returns the raw pointer and hands over ownership to the caller.
68     // The pointer will not be deleted by UniquePtr.
69     T* release() __attribute__((warn_unused_result)) {
70         T* result = mPtr;
71         mPtr = nullptr;
72         return result;
73     }
74 
75     // Takes ownership of the given raw pointer.
76     // If this smart pointer previously owned a different raw pointer, that
77     // raw pointer will be freed.
78     void reset(T* ptr = nullptr) {
79         if (ptr != mPtr) {
80             D()(mPtr);
81             mPtr = ptr;
82         }
83     }
84 
85 private:
86     // The raw pointer.
87     T* mPtr;
88 
89     // Comparing unique pointers is probably a mistake, since they're unique.
90     template <typename T2> bool operator==(const UniquePtr<T2>& p) const;
91     template <typename T2> bool operator!=(const UniquePtr<T2>& p) const;
92 
93     UniquePtr(const UniquePtr&) = delete;
94     UniquePtr & operator=(const UniquePtr&) = delete;
95 };
96 
97 // Partial specialization for array types. Like std::unique_ptr, this removes
98 // operator* and operator-> but adds operator[].
99 template <typename T, typename D>
100 class UniquePtr<T[], D> {
101 public:
102     explicit UniquePtr(T* ptr = nullptr) : mPtr(ptr) {
103     }
104 
105     ~UniquePtr() {
106         reset();
107     }
108 
109     T& operator[](size_t i) const {
110         return mPtr[i];
111     }
112     T* get() const { return mPtr; }
113 
114     T* release() __attribute__((warn_unused_result)) {
115         T* result = mPtr;
116         mPtr = nullptr;
117         return result;
118     }
119 
120     void reset(T* ptr = nullptr) {
121         if (ptr != mPtr) {
122             D()(mPtr);
123             mPtr = ptr;
124         }
125     }
126 
127 private:
128     T* mPtr;
129 
130     UniquePtr(const UniquePtr&) = delete;
131     UniquePtr & operator=(const UniquePtr&) = delete;
132 };
133 
134 } // namespace keymaster
135 
136 #if UNIQUE_PTR_TESTS
137 
138 // Run these tests with:
139 // g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out
140 
141 #include <stdio.h>
142 using namespace keymaster;
143 
144 static void assert(bool b) {
145     if (!b) {
146         fprintf(stderr, "FAIL\n");
147         abort();
148     }
149     fprintf(stderr, "OK\n");
150 }
151 static int cCount = 0;
152 struct C {
153     C() { ++cCount; }
154     ~C() { --cCount; }
155 };
156 static bool freed = false;
157 struct Freer {
158     void operator()(int* p) {
159         assert(*p == 123);
160         free(p);
161         freed = true;
162     }
163 };
164 
165 int main(int argc, char* argv[]) {
166     //
167     // UniquePtr<T> tests...
168     //
169 
170     // Can we free a single object?
171     {
172         UniquePtr<C> c(new C);
173         assert(cCount == 1);
174     }
175     assert(cCount == 0);
176     // Does release work?
177     C* rawC;
178     {
179         UniquePtr<C> c(new C);
180         assert(cCount == 1);
181         rawC = c.release();
182     }
183     assert(cCount == 1);
184     delete rawC;
185     // Does reset work?
186     {
187         UniquePtr<C> c(new C);
188         assert(cCount == 1);
189         c.reset(new C);
190         assert(cCount == 1);
191     }
192     assert(cCount == 0);
193 
194     //
195     // UniquePtr<T[]> tests...
196     //
197 
198     // Can we free an array?
199     {
200         UniquePtr<C[]> cs(new C[4]);
201         assert(cCount == 4);
202     }
203     assert(cCount == 0);
204     // Does release work?
205     {
206         UniquePtr<C[]> c(new C[4]);
207         assert(cCount == 4);
208         rawC = c.release();
209     }
210     assert(cCount == 4);
211     delete[] rawC;
212     // Does reset work?
213     {
214         UniquePtr<C[]> c(new C[4]);
215         assert(cCount == 4);
216         c.reset(new C[2]);
217         assert(cCount == 2);
218     }
219     assert(cCount == 0);
220 
221     //
222     // Custom deleter tests...
223     //
224     assert(!freed);
225     {
226         UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int))));
227         *i = 123;
228     }
229     assert(freed);
230     return 0;
231 }
232 #endif
233 
234 #endif  // INCLUDE_KEYMASTER_UNIQUEPTR_H_
235