OSDN Git Service

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