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.
23template <typename T>
24struct DefaultDelete {
25    enum { type_must_be_complete = sizeof(T) };
26    DefaultDelete() {}
27    void operator()(T* p) const {
28        delete p;
29    }
30};
31
32// Default deleter for array types.
33template <typename T>
34struct 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);
49template <typename T, typename D = DefaultDelete<T> >
50class UniquePtr {
51public:
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
83private:
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[].
98template <typename T, typename D>
99class UniquePtr<T[], D> {
100public:
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
126private:
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
141static void assert(bool b) {
142    if (!b) {
143        fprintf(stderr, "FAIL\n");
144        abort();
145    }
146    fprintf(stderr, "OK\n");
147}
148static int cCount = 0;
149struct C {
150    C() { ++cCount; }
151    ~C() { --cCount; }
152};
153static bool freed = false;
154struct Freer {
155    void operator()(int* p) {
156        assert(*p == 123);
157        free(p);
158        freed = true;
159    }
160};
161
162int 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