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