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 INCLUDE_KEYMASTER_UNIQUEPTR_H_ 18 #define INCLUDE_KEYMASTER_UNIQUEPTR_H_ 19 20 #include <stddef.h> // for size_t 21 22 namespace keymaster { 23 24 // Default deleter for pointer types. 25 template <typename T> 26 struct DefaultDelete { 27 enum { type_must_be_complete = sizeof(T) }; DefaultDeleteDefaultDelete28 DefaultDelete() {} operatorDefaultDelete29 void operator()(T* p) const { 30 delete p; 31 } 32 }; 33 34 // Default deleter for array types. 35 template <typename T> 36 struct DefaultDelete<T[]> { 37 enum { type_must_be_complete = sizeof(T) }; 38 void operator()(T* p) const { 39 delete[] p; 40 } 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 template<typename U, typename UD> 54 friend 55 class UniquePtr; 56 public: 57 UniquePtr() : mPtr(nullptr) {} 58 // Construct a new UniquePtr, taking ownership of the given raw pointer. 59 explicit UniquePtr(T* ptr) : mPtr(ptr) { 60 } 61 UniquePtr(const decltype(nullptr)&) : mPtr(nullptr) {} 62 63 UniquePtr(UniquePtr && other): mPtr(other.mPtr) { 64 other.mPtr = nullptr; 65 } 66 67 template<typename U> 68 UniquePtr(UniquePtr<U> && other): mPtr(other.mPtr) { 69 other.mPtr = nullptr; 70 } 71 UniquePtr& operator=(UniquePtr && other) { 72 if (&other != this) { 73 reset(); 74 mPtr = other.release(); 75 } 76 return *this; 77 } 78 79 ~UniquePtr() { 80 reset(); 81 } 82 83 // Accessors. 84 T& operator*() const { return *mPtr; } 85 T* operator->() const { return mPtr; } 86 T* get() const { return mPtr; } 87 88 operator bool() const { return mPtr != nullptr; } 89 90 // Returns the raw pointer and hands over ownership to the caller. 91 // The pointer will not be deleted by UniquePtr. 92 T* release() __attribute__((warn_unused_result)) { 93 T* result = mPtr; 94 mPtr = nullptr; 95 return result; 96 } 97 98 // Takes ownership of the given raw pointer. 99 // If this smart pointer previously owned a different raw pointer, that 100 // raw pointer will be freed. 101 void reset(T* ptr = nullptr) { 102 if (ptr != mPtr) { 103 D()(mPtr); 104 mPtr = ptr; 105 } 106 } 107 108 private: 109 // The raw pointer. 110 T* mPtr; 111 112 // Comparing unique pointers is probably a mistake, since they're unique. 113 template <typename T2> bool operator==(const UniquePtr<T2>& p) const; 114 template <typename T2> bool operator!=(const UniquePtr<T2>& p) const; 115 116 UniquePtr(const UniquePtr&) = delete; 117 UniquePtr & operator=(const UniquePtr&) = delete; 118 }; 119 120 // Partial specialization for array types. Like std::unique_ptr, this removes 121 // operator* and operator-> but adds operator[]. 122 template <typename T, typename D> 123 class UniquePtr<T[], D> { 124 public: 125 UniquePtr() : mPtr(nullptr) {} 126 explicit UniquePtr(T* ptr) : mPtr(ptr) { 127 } 128 UniquePtr(const decltype(nullptr)&) : mPtr(nullptr) {} 129 130 UniquePtr(UniquePtr && other): mPtr(other.mPtr) { 131 other.mPtr = nullptr; 132 } 133 UniquePtr& operator=(UniquePtr && other) { 134 if (&other != this) { 135 reset(); 136 mPtr = other.release(); 137 } 138 return *this; 139 } 140 141 ~UniquePtr() { 142 reset(); 143 } 144 145 T& operator[](size_t i) const { 146 return mPtr[i]; 147 } 148 T* get() const { return mPtr; } 149 150 T* release() __attribute__((warn_unused_result)) { 151 T* result = mPtr; 152 mPtr = nullptr; 153 return result; 154 } 155 156 operator bool() const { return mPtr != nullptr; } 157 158 void reset(T* ptr = nullptr) { 159 if (ptr != mPtr) { 160 D()(mPtr); 161 mPtr = ptr; 162 } 163 } 164 165 private: 166 T* mPtr; 167 168 UniquePtr(const UniquePtr&) = delete; 169 UniquePtr & operator=(const UniquePtr&) = delete; 170 }; 171 172 } // namespace keymaster 173 174 #if UNIQUE_PTR_TESTS 175 176 // Run these tests with: 177 // g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out 178 179 #include <stdio.h> 180 using namespace keymaster; 181 182 static void assert(bool b) { 183 if (!b) { 184 fprintf(stderr, "FAIL\n"); 185 abort(); 186 } 187 fprintf(stderr, "OK\n"); 188 } 189 static int cCount = 0; 190 struct C { 191 C() { ++cCount; } 192 ~C() { --cCount; } 193 }; 194 static bool freed = false; 195 struct Freer { 196 void operator()(int* p) { 197 assert(*p == 123); 198 free(p); 199 freed = true; 200 } 201 }; 202 203 int main(int argc, char* argv[]) { 204 // 205 // UniquePtr<T> tests... 206 // 207 208 // Can we free a single object? 209 { 210 UniquePtr<C> c(new C); 211 assert(cCount == 1); 212 } 213 assert(cCount == 0); 214 // Does release work? 215 C* rawC; 216 { 217 UniquePtr<C> c(new C); 218 assert(cCount == 1); 219 rawC = c.release(); 220 } 221 assert(cCount == 1); 222 delete rawC; 223 // Does reset work? 224 { 225 UniquePtr<C> c(new C); 226 assert(cCount == 1); 227 c.reset(new C); 228 assert(cCount == 1); 229 } 230 assert(cCount == 0); 231 232 // 233 // UniquePtr<T[]> tests... 234 // 235 236 // Can we free an array? 237 { 238 UniquePtr<C[]> cs(new C[4]); 239 assert(cCount == 4); 240 } 241 assert(cCount == 0); 242 // Does release work? 243 { 244 UniquePtr<C[]> c(new C[4]); 245 assert(cCount == 4); 246 rawC = c.release(); 247 } 248 assert(cCount == 4); 249 delete[] rawC; 250 // Does reset work? 251 { 252 UniquePtr<C[]> c(new C[4]); 253 assert(cCount == 4); 254 c.reset(new C[2]); 255 assert(cCount == 2); 256 } 257 assert(cCount == 0); 258 259 // 260 // Custom deleter tests... 261 // 262 assert(!freed); 263 { 264 UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int)))); 265 *i = 123; 266 } 267 assert(freed); 268 return 0; 269 } 270 #endif 271 272 #endif // INCLUDE_KEYMASTER_UNIQUEPTR_H_ 273