reed@android.com | 8a1c16f | 2008-12-17 15:59:43 +0000 | [diff] [blame^] | 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: |
| 38 | SkAutoTCallVProc(T* obj): fObj(obj) {} |
| 39 | ~SkAutoTCallVProc() { if (fObj) P(fObj); } |
| 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: |
| 55 | SkAutoTCallIProc(T* obj): fObj(obj) {} |
| 56 | ~SkAutoTCallIProc() { if (fObj) P(fObj); } |
| 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: |
| 64 | SkAutoTDelete(T* obj) : fObj(obj) {} |
| 65 | ~SkAutoTDelete() { delete fObj; } |
| 66 | |
| 67 | T* get() const { return fObj; } |
| 68 | void free() { delete fObj; fObj = NULL; } |
| 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: |
| 77 | SkAutoTDeleteArray(T array[]) : fArray(array) {} |
| 78 | ~SkAutoTDeleteArray() { delete[] fArray; } |
| 79 | |
| 80 | T* get() const { return fArray; } |
| 81 | void free() { delete[] fArray; fArray = NULL; } |
| 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 | */ |
| 94 | SkAutoTArray(size_t count) { |
| 95 | fArray = NULL; |
| 96 | if (count) { |
| 97 | fArray = new T[count]; |
| 98 | } |
| 99 | SkDEBUGCODE(fCount = count;) |
| 100 | } |
| 101 | |
| 102 | ~SkAutoTArray() { |
| 103 | delete[] fArray; |
| 104 | } |
| 105 | |
| 106 | /** Return the array of T elements. Will be NULL if count == 0 |
| 107 | */ |
| 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 | */ |
| 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 | |
| 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 | */ |
| 153 | size_t count() const { return fCount; } |
| 154 | |
| 155 | /** Return the array of T elements. Will be NULL if count == 0 |
| 156 | */ |
| 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: |
| 178 | SkAutoTMalloc(size_t count) |
| 179 | { |
| 180 | fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP); |
| 181 | } |
| 182 | ~SkAutoTMalloc() |
| 183 | { |
| 184 | sk_free(fPtr); |
| 185 | } |
| 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: |
| 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 | } |
| 201 | ~SkAutoSTMalloc() |
| 202 | { |
| 203 | if (fPtr != fTStorage) |
| 204 | sk_free(fPtr); |
| 205 | } |
| 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 | |