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