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 template <typename T> class SkAutoTDelete : SkNoncopyable { 63 public: SkAutoTDelete(T * obj)64 SkAutoTDelete(T* obj) : fObj(obj) {} ~SkAutoTDelete()65 ~SkAutoTDelete() { delete fObj; } 66 get()67 T* get() const { return fObj; } free()68 void free() { delete fObj; fObj = NULL; } detach()69 T* detach() { T* obj = fObj; fObj = NULL; return obj; } 70 71 private: 72 T* fObj; 73 }; 74 75 template <typename T> class SkAutoTDeleteArray : SkNoncopyable { 76 public: SkAutoTDeleteArray(T array[])77 SkAutoTDeleteArray(T array[]) : fArray(array) {} ~SkAutoTDeleteArray()78 ~SkAutoTDeleteArray() { delete[] fArray; } 79 get()80 T* get() const { return fArray; } free()81 void free() { delete[] fArray; fArray = NULL; } detach()82 T* detach() { T* array = fArray; fArray = NULL; return array; } 83 84 private: 85 T* fArray; 86 }; 87 88 /** Allocate an array of T elements, and free the array in the destructor 89 */ 90 template <typename T> class SkAutoTArray : SkNoncopyable { 91 public: 92 /** Allocate count number of T elements 93 */ SkAutoTArray(size_t count)94 SkAutoTArray(size_t count) { 95 fArray = NULL; 96 if (count) { 97 fArray = new T[count]; 98 } 99 SkDEBUGCODE(fCount = count;) 100 } 101 ~SkAutoTArray()102 ~SkAutoTArray() { 103 delete[] fArray; 104 } 105 106 /** Return the array of T elements. Will be NULL if count == 0 107 */ get()108 T* get() const { return fArray; } 109 110 /** Return the nth element in the array 111 */ 112 T& operator[](int index) const { 113 SkASSERT((unsigned)index < fCount); 114 return fArray[index]; 115 } 116 117 private: 118 T* fArray; 119 SkDEBUGCODE(size_t fCount;) 120 }; 121 122 /** Wraps SkAutoTArray, with room for up to N elements preallocated 123 */ 124 template <size_t N, typename T> class SkAutoSTArray : SkNoncopyable { 125 public: 126 /** Allocate count number of T elements 127 */ SkAutoSTArray(size_t count)128 SkAutoSTArray(size_t count) { 129 if (count > N) { 130 fArray = new T[count]; 131 } else if (count) { 132 fArray = new (fStorage) T[count]; 133 } else { 134 fArray = NULL; 135 } 136 fCount = count; 137 } 138 ~SkAutoSTArray()139 ~SkAutoSTArray() { 140 if (fCount > N) { 141 delete[] fArray; 142 } else { 143 T* start = fArray; 144 T* iter = start + fCount; 145 while (iter > start) { 146 (--iter)->~T(); 147 } 148 } 149 } 150 151 /** Return the number of T elements in the array 152 */ count()153 size_t count() const { return fCount; } 154 155 /** Return the array of T elements. Will be NULL if count == 0 156 */ get()157 T* get() const { return fArray; } 158 159 /** Return the nth element in the array 160 */ 161 T& operator[](int index) const { 162 SkASSERT((unsigned)index < fCount); 163 return fArray[index]; 164 } 165 166 private: 167 size_t fCount; 168 T* fArray; 169 // since we come right after fArray, fStorage should be properly aligned 170 char fStorage[N * sizeof(T)]; 171 }; 172 173 /** Allocate a temp array on the stack/heap. 174 Does NOT call any constructors/destructors on T (i.e. T must be POD) 175 */ 176 template <typename T> class SkAutoTMalloc : SkNoncopyable { 177 public: SkAutoTMalloc(size_t count)178 SkAutoTMalloc(size_t count) 179 { 180 fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); 181 } ~SkAutoTMalloc()182 ~SkAutoTMalloc() 183 { 184 sk_free(fPtr); 185 } get()186 T* get() const { return fPtr; } 187 188 private: 189 T* fPtr; 190 }; 191 192 template <size_t N, typename T> class SkAutoSTMalloc : SkNoncopyable { 193 public: SkAutoSTMalloc(size_t count)194 SkAutoSTMalloc(size_t count) 195 { 196 if (count <= N) 197 fPtr = fTStorage; 198 else 199 fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); 200 } ~SkAutoSTMalloc()201 ~SkAutoSTMalloc() 202 { 203 if (fPtr != fTStorage) 204 sk_free(fPtr); 205 } get()206 T* get() const { return fPtr; } 207 208 private: 209 T* fPtr; 210 union { 211 uint32_t fStorage32[(N*sizeof(T) + 3) >> 2]; 212 T fTStorage[1]; // do NOT want to invoke T::T() 213 }; 214 }; 215 216 #endif 217 218