1 /* 2 * Copyright 2010 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrAllocator_DEFINED 9 #define GrAllocator_DEFINED 10 11 #include "GrConfig.h" 12 #include "GrTypes.h" 13 #include "SkTArray.h" 14 #include "SkTypes.h" 15 16 class GrAllocator : SkNoncopyable { 17 public: 18 ~GrAllocator() { 19 reset(); 20 } 21 22 /** 23 * Create an allocator 24 * 25 * @param itemSize the size of each item to allocate 26 * @param itemsPerBlock the number of items to allocate at once 27 * @param initialBlock optional memory to use for the first block. 28 * Must be at least itemSize*itemsPerBlock sized. 29 * Caller is responsible for freeing this memory. 30 */ 31 GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock) : 32 fItemSize(itemSize), 33 fItemsPerBlock(itemsPerBlock), 34 fOwnFirstBlock(NULL == initialBlock), 35 fCount(0) { 36 SkASSERT(itemsPerBlock > 0); 37 fBlockSize = fItemSize * fItemsPerBlock; 38 fBlocks.push_back() = initialBlock; 39 SkDEBUGCODE(if (!fOwnFirstBlock) {*((char*)initialBlock+fBlockSize-1)='a';} ); 40 } 41 42 /* 43 * Set first block of memory to write into. Must be called before any other methods. 44 * This requires that you have passed NULL in the constructor. 45 * 46 * @param initialBlock optional memory to use for the first block. 47 * Must be at least itemSize*itemsPerBlock sized. 48 * Caller is responsible for freeing this memory. 49 */ 50 void setInitialBlock(void* initialBlock) { 51 SkASSERT(0 == fCount); 52 SkASSERT(1 == fBlocks.count()); 53 SkASSERT(NULL == fBlocks.back()); 54 fOwnFirstBlock = false; 55 fBlocks.back() = initialBlock; 56 } 57 58 /** 59 * Adds an item and returns pointer to it. 60 * 61 * @return pointer to the added item. 62 */ 63 void* push_back() { 64 int indexInBlock = fCount % fItemsPerBlock; 65 // we always have at least one block 66 if (0 == indexInBlock) { 67 if (0 != fCount) { 68 fBlocks.push_back() = sk_malloc_throw(fBlockSize); 69 } else if (fOwnFirstBlock) { 70 fBlocks[0] = sk_malloc_throw(fBlockSize); 71 } 72 } 73 void* ret = (char*)fBlocks[fCount/fItemsPerBlock] + 74 fItemSize * indexInBlock; 75 ++fCount; 76 return ret; 77 } 78 79 /** 80 * removes all added items 81 */ 82 void reset() { 83 int blockCount = SkTMax((unsigned)1, 84 GrUIDivRoundUp(fCount, fItemsPerBlock)); 85 for (int i = 1; i < blockCount; ++i) { 86 sk_free(fBlocks[i]); 87 } 88 if (fOwnFirstBlock) { 89 sk_free(fBlocks[0]); 90 fBlocks[0] = NULL; 91 } 92 fBlocks.pop_back_n(blockCount-1); 93 fCount = 0; 94 } 95 96 /** 97 * count of items 98 */ 99 int count() const { 100 return fCount; 101 } 102 103 /** 104 * is the count 0 105 */ 106 bool empty() const { return fCount == 0; } 107 108 /** 109 * access last item, only call if count() != 0 110 */ 111 void* back() { 112 SkASSERT(fCount); 113 return (*this)[fCount-1]; 114 } 115 116 /** 117 * access last item, only call if count() != 0 118 */ 119 const void* back() const { 120 SkASSERT(fCount); 121 return (*this)[fCount-1]; 122 } 123 124 /** 125 * access item by index. 126 */ 127 void* operator[] (int i) { 128 SkASSERT(i >= 0 && i < fCount); 129 return (char*)fBlocks[i / fItemsPerBlock] + 130 fItemSize * (i % fItemsPerBlock); 131 } 132 133 /** 134 * access item by index. 135 */ 136 const void* operator[] (int i) const { 137 SkASSERT(i >= 0 && i < fCount); 138 return (const char*)fBlocks[i / fItemsPerBlock] + 139 fItemSize * (i % fItemsPerBlock); 140 } 141 142 private: 143 static const int NUM_INIT_BLOCK_PTRS = 8; 144 145 SkSTArray<NUM_INIT_BLOCK_PTRS, void*> fBlocks; 146 size_t fBlockSize; 147 size_t fItemSize; 148 int fItemsPerBlock; 149 bool fOwnFirstBlock; 150 int fCount; 151 152 typedef SkNoncopyable INHERITED; 153 }; 154 155 template <typename T> 156 class GrTAllocator : SkNoncopyable { 157 public: 158 virtual ~GrTAllocator() { this->reset(); }; 159 160 /** 161 * Create an allocator 162 * 163 * @param itemsPerBlock the number of items to allocate at once 164 */ 165 explicit GrTAllocator(int itemsPerBlock) 166 : fAllocator(sizeof(T), itemsPerBlock, NULL) {} 167 168 /** 169 * Adds an item and returns it. 170 * 171 * @return the added item. 172 */ 173 T& push_back() { 174 void* item = fAllocator.push_back(); 175 SkASSERT(NULL != item); 176 SkNEW_PLACEMENT(item, T); 177 return *(T*)item; 178 } 179 180 T& push_back(const T& t) { 181 void* item = fAllocator.push_back(); 182 SkASSERT(NULL != item); 183 SkNEW_PLACEMENT_ARGS(item, T, (t)); 184 return *(T*)item; 185 } 186 187 /** 188 * removes all added items 189 */ 190 void reset() { 191 int c = fAllocator.count(); 192 for (int i = 0; i < c; ++i) { 193 ((T*)fAllocator[i])->~T(); 194 } 195 fAllocator.reset(); 196 } 197 198 /** 199 * count of items 200 */ 201 int count() const { 202 return fAllocator.count(); 203 } 204 205 /** 206 * is the count 0 207 */ 208 bool empty() const { return fAllocator.empty(); } 209 210 /** 211 * access last item, only call if count() != 0 212 */ 213 T& back() { 214 return *(T*)fAllocator.back(); 215 } 216 217 /** 218 * access last item, only call if count() != 0 219 */ 220 const T& back() const { 221 return *(const T*)fAllocator.back(); 222 } 223 224 /** 225 * access item by index. 226 */ 227 T& operator[] (int i) { 228 return *(T*)(fAllocator[i]); 229 } 230 231 /** 232 * access item by index. 233 */ 234 const T& operator[] (int i) const { 235 return *(const T*)(fAllocator[i]); 236 } 237 238 protected: 239 /* 240 * Set first block of memory to write into. Must be called before any other methods. 241 * 242 * @param initialBlock optional memory to use for the first block. 243 * Must be at least size(T)*itemsPerBlock sized. 244 * Caller is responsible for freeing this memory. 245 */ 246 void setInitialBlock(void* initialBlock) { 247 fAllocator.setInitialBlock(initialBlock); 248 } 249 250 private: 251 GrAllocator fAllocator; 252 typedef SkNoncopyable INHERITED; 253 }; 254 255 template <int N, typename T> class GrSTAllocator : public GrTAllocator<T> { 256 private: 257 typedef GrTAllocator<T> INHERITED; 258 259 public: 260 GrSTAllocator() : INHERITED(N) { 261 this->setInitialBlock(fStorage.get()); 262 } 263 264 private: 265 SkAlignedSTStorage<N, T> fStorage; 266 }; 267 268 #endif 269