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