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 public: 54 // Construct a new UniquePtr, taking ownership of the given raw pointer. 55 explicit UniquePtr(T* ptr = nullptr) : mPtr(ptr) { 56 } 57 58 ~UniquePtr() { 59 reset(); 60 } 61 62 // Accessors. 63 T& operator*() const { return *mPtr; } 64 T* operator->() const { return mPtr; } 65 T* get() const { return mPtr; } 66 67 // Returns the raw pointer and hands over ownership to the caller. 68 // The pointer will not be deleted by UniquePtr. 69 T* release() __attribute__((warn_unused_result)) { 70 T* result = mPtr; 71 mPtr = nullptr; 72 return result; 73 } 74 75 // Takes ownership of the given raw pointer. 76 // If this smart pointer previously owned a different raw pointer, that 77 // raw pointer will be freed. 78 void reset(T* ptr = nullptr) { 79 if (ptr != mPtr) { 80 D()(mPtr); 81 mPtr = ptr; 82 } 83 } 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> bool operator==(const UniquePtr<T2>& p) const; 91 template <typename T2> bool operator!=(const UniquePtr<T2>& p) const; 92 93 UniquePtr(const UniquePtr&) = delete; 94 UniquePtr & operator=(const UniquePtr&) = delete; 95 }; 96 97 // Partial specialization for array types. Like std::unique_ptr, this removes 98 // operator* and operator-> but adds operator[]. 99 template <typename T, typename D> 100 class UniquePtr<T[], D> { 101 public: 102 explicit UniquePtr(T* ptr = nullptr) : mPtr(ptr) { 103 } 104 105 ~UniquePtr() { 106 reset(); 107 } 108 109 T& operator[](size_t i) const { 110 return mPtr[i]; 111 } 112 T* get() const { return mPtr; } 113 114 T* release() __attribute__((warn_unused_result)) { 115 T* result = mPtr; 116 mPtr = nullptr; 117 return result; 118 } 119 120 void reset(T* ptr = nullptr) { 121 if (ptr != mPtr) { 122 D()(mPtr); 123 mPtr = ptr; 124 } 125 } 126 127 private: 128 T* mPtr; 129 130 UniquePtr(const UniquePtr&) = delete; 131 UniquePtr & operator=(const UniquePtr&) = delete; 132 }; 133 134 } // namespace keymaster 135 136 #if UNIQUE_PTR_TESTS 137 138 // Run these tests with: 139 // g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out 140 141 #include <stdio.h> 142 using namespace keymaster; 143 144 static void assert(bool b) { 145 if (!b) { 146 fprintf(stderr, "FAIL\n"); 147 abort(); 148 } 149 fprintf(stderr, "OK\n"); 150 } 151 static int cCount = 0; 152 struct C { 153 C() { ++cCount; } 154 ~C() { --cCount; } 155 }; 156 static bool freed = false; 157 struct Freer { 158 void operator()(int* p) { 159 assert(*p == 123); 160 free(p); 161 freed = true; 162 } 163 }; 164 165 int main(int argc, char* argv[]) { 166 // 167 // UniquePtr<T> tests... 168 // 169 170 // Can we free a single object? 171 { 172 UniquePtr<C> c(new C); 173 assert(cCount == 1); 174 } 175 assert(cCount == 0); 176 // Does release work? 177 C* rawC; 178 { 179 UniquePtr<C> c(new C); 180 assert(cCount == 1); 181 rawC = c.release(); 182 } 183 assert(cCount == 1); 184 delete rawC; 185 // Does reset work? 186 { 187 UniquePtr<C> c(new C); 188 assert(cCount == 1); 189 c.reset(new C); 190 assert(cCount == 1); 191 } 192 assert(cCount == 0); 193 194 // 195 // UniquePtr<T[]> tests... 196 // 197 198 // Can we free an array? 199 { 200 UniquePtr<C[]> cs(new C[4]); 201 assert(cCount == 4); 202 } 203 assert(cCount == 0); 204 // Does release work? 205 { 206 UniquePtr<C[]> c(new C[4]); 207 assert(cCount == 4); 208 rawC = c.release(); 209 } 210 assert(cCount == 4); 211 delete[] rawC; 212 // Does reset work? 213 { 214 UniquePtr<C[]> c(new C[4]); 215 assert(cCount == 4); 216 c.reset(new C[2]); 217 assert(cCount == 2); 218 } 219 assert(cCount == 0); 220 221 // 222 // Custom deleter tests... 223 // 224 assert(!freed); 225 { 226 UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int)))); 227 *i = 123; 228 } 229 assert(freed); 230 return 0; 231 } 232 #endif 233 234 #endif // INCLUDE_KEYMASTER_UNIQUEPTR_H_ 235