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