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.
31template <typename T>
32struct 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.
41template <typename T>
42struct 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);
57template <typename T, typename D = DefaultDelete<T> >
58class UniquePtr {
59public:
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
91private:
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[].
106template <typename T, typename D>
107class UniquePtr<T[], D> {
108public:
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
134private:
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
149static void assert(bool b) {
150    if (!b) {
151        fprintf(stderr, "FAIL\n");
152        abort();
153    }
154    fprintf(stderr, "OK\n");
155}
156static int cCount = 0;
157struct C {
158    C() { ++cCount; }
159    ~C() { --cCount; }
160};
161static bool freed = false;
162struct Freer {
163    void operator()(int* p) {
164        assert(*p == 123);
165        free(p);
166        freed = true;
167    }
168};
169
170int 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
240