1 /* 2 * Copyright (C) 2006 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 SkTemplates_DEFINED 18 #define SkTemplates_DEFINED 19 20 #include "SkTypes.h" 21 22 /** \file SkTemplates.h 23 24 This file contains light-weight template classes for type-safe and exception-safe 25 resource management. 26 */ 27 28 /** \class SkAutoTCallVProc 29 30 Call a function when this goes out of scope. The template uses two 31 parameters, the object, and a function that is to be called in the destructor. 32 If detach() is called, the object reference is set to null. If the object 33 reference is null when the destructor is called, we do not call the 34 function. 35 */ 36 template <typename T, void (*P)(T*)> class SkAutoTCallVProc : SkNoncopyable { 37 public: SkAutoTCallVProc(T * obj)38 SkAutoTCallVProc(T* obj): fObj(obj) {} ~SkAutoTCallVProc()39 ~SkAutoTCallVProc() { if (fObj) P(fObj); } detach()40 T* detach() { T* obj = fObj; fObj = NULL; return obj; } 41 private: 42 T* fObj; 43 }; 44 45 /** \class SkAutoTCallIProc 46 47 Call a function when this goes out of scope. The template uses two 48 parameters, the object, and a function that is to be called in the destructor. 49 If detach() is called, the object reference is set to null. If the object 50 reference is null when the destructor is called, we do not call the 51 function. 52 */ 53 template <typename T, int (*P)(T*)> class SkAutoTCallIProc : SkNoncopyable { 54 public: SkAutoTCallIProc(T * obj)55 SkAutoTCallIProc(T* obj): fObj(obj) {} ~SkAutoTCallIProc()56 ~SkAutoTCallIProc() { if (fObj) P(fObj); } detach()57 T* detach() { T* obj = fObj; fObj = NULL; return obj; } 58 private: 59 T* fObj; 60 }; 61 62 // See also SkTScopedPtr. 63 template <typename T> class SkAutoTDelete : SkNoncopyable { 64 public: fObj(obj)65 SkAutoTDelete(T* obj, bool deleteWhenDone = true) : fObj(obj) { 66 fDeleteWhenDone = deleteWhenDone; 67 } ~SkAutoTDelete()68 ~SkAutoTDelete() { if (fDeleteWhenDone) delete fObj; } 69 get()70 T* get() const { return fObj; } free()71 void free() { delete fObj; fObj = NULL; } detach()72 T* detach() { T* obj = fObj; fObj = NULL; return obj; } 73 74 private: 75 T* fObj; 76 bool fDeleteWhenDone; 77 }; 78 79 template <typename T> class SkAutoTDeleteArray : SkNoncopyable { 80 public: SkAutoTDeleteArray(T array[])81 SkAutoTDeleteArray(T array[]) : fArray(array) {} ~SkAutoTDeleteArray()82 ~SkAutoTDeleteArray() { delete[] fArray; } 83 get()84 T* get() const { return fArray; } free()85 void free() { delete[] fArray; fArray = NULL; } detach()86 T* detach() { T* array = fArray; fArray = NULL; return array; } 87 88 private: 89 T* fArray; 90 }; 91 92 /** Allocate an array of T elements, and free the array in the destructor 93 */ 94 template <typename T> class SkAutoTArray : SkNoncopyable { 95 public: 96 /** Allocate count number of T elements 97 */ SkAutoTArray(size_t count)98 SkAutoTArray(size_t count) { 99 fArray = NULL; 100 if (count) { 101 fArray = new T[count]; 102 } 103 SkDEBUGCODE(fCount = count;) 104 } 105 ~SkAutoTArray()106 ~SkAutoTArray() { 107 delete[] fArray; 108 } 109 110 /** Return the array of T elements. Will be NULL if count == 0 111 */ get()112 T* get() const { return fArray; } 113 114 /** Return the nth element in the array 115 */ 116 T& operator[](int index) const { 117 SkASSERT((unsigned)index < fCount); 118 return fArray[index]; 119 } 120 121 private: 122 T* fArray; 123 SkDEBUGCODE(size_t fCount;) 124 }; 125 126 /** Wraps SkAutoTArray, with room for up to N elements preallocated 127 */ 128 template <size_t N, typename T> class SkAutoSTArray : SkNoncopyable { 129 public: 130 /** Allocate count number of T elements 131 */ SkAutoSTArray(size_t count)132 SkAutoSTArray(size_t count) { 133 if (count > N) { 134 fArray = new T[count]; 135 } else if (count) { 136 fArray = new (fStorage) T[count]; 137 } else { 138 fArray = NULL; 139 } 140 fCount = count; 141 } 142 ~SkAutoSTArray()143 ~SkAutoSTArray() { 144 if (fCount > N) { 145 delete[] fArray; 146 } else { 147 T* start = fArray; 148 T* iter = start + fCount; 149 while (iter > start) { 150 (--iter)->~T(); 151 } 152 } 153 } 154 155 /** Return the number of T elements in the array 156 */ count()157 size_t count() const { return fCount; } 158 159 /** Return the array of T elements. Will be NULL if count == 0 160 */ get()161 T* get() const { return fArray; } 162 163 /** Return the nth element in the array 164 */ 165 T& operator[](int index) const { 166 SkASSERT((unsigned)index < fCount); 167 return fArray[index]; 168 } 169 170 private: 171 size_t fCount; 172 T* fArray; 173 // since we come right after fArray, fStorage should be properly aligned 174 char fStorage[N * sizeof(T)]; 175 }; 176 177 /** Allocate a temp array on the stack/heap. 178 Does NOT call any constructors/destructors on T (i.e. T must be POD) 179 */ 180 template <typename T> class SkAutoTMalloc : SkNoncopyable { 181 public: SkAutoTMalloc(size_t count)182 SkAutoTMalloc(size_t count) 183 { 184 fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); 185 } ~SkAutoTMalloc()186 ~SkAutoTMalloc() 187 { 188 sk_free(fPtr); 189 } get()190 T* get() const { return fPtr; } 191 192 private: 193 T* fPtr; 194 }; 195 196 template <size_t N, typename T> class SkAutoSTMalloc : SkNoncopyable { 197 public: SkAutoSTMalloc(size_t count)198 SkAutoSTMalloc(size_t count) 199 { 200 if (count <= N) 201 fPtr = fTStorage; 202 else 203 fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); 204 } ~SkAutoSTMalloc()205 ~SkAutoSTMalloc() 206 { 207 if (fPtr != fTStorage) 208 sk_free(fPtr); 209 } get()210 T* get() const { return fPtr; } 211 212 private: 213 T* fPtr; 214 union { 215 uint32_t fStorage32[(N*sizeof(T) + 3) >> 2]; 216 T fTStorage[1]; // do NOT want to invoke T::T() 217 }; 218 }; 219 220 #endif 221 222