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