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