• 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 <stdlib.h>  // For NULL.
21 
22 // This is a fake declaration of std::swap to avoid including <algorithm>
23 namespace std {
24 template <class T>
25 void swap(T&, T&);
26 }
27 
28 // Default deleter for pointer types.
29 template <typename T>
30 struct DefaultDelete {
31     enum { type_must_be_complete = sizeof(T) };
DefaultDeleteDefaultDelete32     DefaultDelete() {}
operatorDefaultDelete33     void operator()(T* p) const { delete p; }
34 };
35 
36 // Default deleter for array types.
37 template <typename T>
38 struct DefaultDelete<T[]> {
39     enum { type_must_be_complete = sizeof(T) };
40     void operator()(T* p) const { delete[] p; }
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 = NULL) : mPtr(ptr) {}
56 
57     ~UniquePtr() { reset(); }
58 
59     // Accessors.
60     T& operator*() const { return *mPtr; }
61     T* operator->() const { return mPtr; }
62     T* get() const { return mPtr; }
63 
64     // Returns the raw pointer and hands over ownership to the caller.
65     // The pointer will not be deleted by UniquePtr.
66     T* release() __attribute__((warn_unused_result)) {
67         T* result = mPtr;
68         mPtr = NULL;
69         return result;
70     }
71 
72     // Takes ownership of the given raw pointer.
73     // If this smart pointer previously owned a different raw pointer, that
74     // raw pointer will be freed.
75     void reset(T* ptr = NULL) {
76         if (ptr != mPtr) {
77             D()(mPtr);
78             mPtr = ptr;
79         }
80     }
81 
82     // Swap with another unique pointer.
83     void swap(UniquePtr<T>& other) { std::swap(mPtr, other.mPtr); }
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>
91     bool operator==(const UniquePtr<T2>& p) const;
92     template <typename T2>
93     bool operator!=(const UniquePtr<T2>& p) const;
94 
95     // Disallow copy and assignment.
96     UniquePtr(const UniquePtr&);
97     void operator=(const UniquePtr&);
98 };
99 
100 // Partial specialization for array types. Like std::unique_ptr, this removes
101 // operator* and operator-> but adds operator[].
102 template <typename T, typename D>
103 class UniquePtr<T[], D> {
104 public:
105     explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {}
106 
107     ~UniquePtr() { reset(); }
108 
109     T& operator[](size_t i) const { return mPtr[i]; }
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 assignment.
129     UniquePtr(const UniquePtr&);
130     void operator=(const UniquePtr&);
131 };
132 
133 #if UNIQUE_PTR_TESTS
134 
135 // Run these tests with:
136 // g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out
137 
138 #include <stdio.h>
139 
140 static void assert(bool b) {
141     if (!b) {
142         fprintf(stderr, "FAIL\n");
143         abort();
144     }
145     fprintf(stderr, "OK\n");
146 }
147 static int cCount = 0;
148 struct C {
149     C() { ++cCount; }
150     ~C() { --cCount; }
151 };
152 static bool freed = false;
153 struct Freer {
154     void operator()(int* p) {
155         assert(*p == 123);
156         free(p);
157         freed = true;
158     }
159 };
160 
161 int main(int argc, char* argv[]) {
162     //
163     // UniquePtr<T> tests...
164     //
165 
166     // Can we free a single object?
167     {
168         UniquePtr<C> c(new C);
169         assert(cCount == 1);
170     }
171     assert(cCount == 0);
172     // Does release work?
173     C* rawC;
174     {
175         UniquePtr<C> c(new C);
176         assert(cCount == 1);
177         rawC = c.release();
178     }
179     assert(cCount == 1);
180     delete rawC;
181     // Does reset work?
182     {
183         UniquePtr<C> c(new C);
184         assert(cCount == 1);
185         c.reset(new C);
186         assert(cCount == 1);
187     }
188     assert(cCount == 0);
189 
190     //
191     // UniquePtr<T[]> tests...
192     //
193 
194     // Can we free an array?
195     {
196         UniquePtr<C[]> cs(new C[4]);
197         assert(cCount == 4);
198     }
199     assert(cCount == 0);
200     // Does release work?
201     {
202         UniquePtr<C[]> c(new C[4]);
203         assert(cCount == 4);
204         rawC = c.release();
205     }
206     assert(cCount == 4);
207     delete[] rawC;
208     // Does reset work?
209     {
210         UniquePtr<C[]> c(new C[4]);
211         assert(cCount == 4);
212         c.reset(new C[2]);
213         assert(cCount == 2);
214     }
215     assert(cCount == 0);
216 
217     //
218     // Custom deleter tests...
219     //
220     assert(!freed);
221     {
222         UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int))));
223         *i = 123;
224     }
225     assert(freed);
226     return 0;
227 }
228 #endif
229 
230 #endif  // UNIQUE_PTR_H_included
231