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