2 * Copyright 2010 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef GrAllocator_DEFINED
9 #define GrAllocator_DEFINED
16 class GrAllocator : SkNoncopyable {
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.
31 GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock) :
33 fItemsPerBlock(itemsPerBlock),
34 fOwnFirstBlock(NULL == initialBlock),
36 SkASSERT(itemsPerBlock > 0);
37 fBlockSize = fItemSize * fItemsPerBlock;
38 fBlocks.push_back() = initialBlock;
39 SkDEBUGCODE(if (!fOwnFirstBlock) {*((char*)initialBlock+fBlockSize-1)='a';} );
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.
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.
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;
59 * Adds an item and returns pointer to it.
61 * @return pointer to the added item.
64 int indexInBlock = fCount % fItemsPerBlock;
65 // we always have at least one block
66 if (0 == indexInBlock) {
68 fBlocks.push_back() = sk_malloc_throw(fBlockSize);
69 } else if (fOwnFirstBlock) {
70 fBlocks[0] = sk_malloc_throw(fBlockSize);
73 void* ret = (char*)fBlocks[fCount/fItemsPerBlock] +
74 fItemSize * indexInBlock;
80 * removes all added items
83 int blockCount = SkTMax((unsigned)1,
84 GrUIDivRoundUp(fCount, fItemsPerBlock));
85 for (int i = 1; i < blockCount; ++i) {
92 fBlocks.pop_back_n(blockCount-1);
106 bool empty() const { return fCount == 0; }
109 * access last item, only call if count() != 0
113 return (*this)[fCount-1];
117 * access last item, only call if count() != 0
119 const void* back() const {
121 return (*this)[fCount-1];
125 * access item by index.
127 void* operator[] (int i) {
128 SkASSERT(i >= 0 && i < fCount);
129 return (char*)fBlocks[i / fItemsPerBlock] +
130 fItemSize * (i % fItemsPerBlock);
134 * access item by index.
136 const void* operator[] (int i) const {
137 SkASSERT(i >= 0 && i < fCount);
138 return (const char*)fBlocks[i / fItemsPerBlock] +
139 fItemSize * (i % fItemsPerBlock);
143 static const int NUM_INIT_BLOCK_PTRS = 8;
145 SkSTArray<NUM_INIT_BLOCK_PTRS, void*> fBlocks;
152 typedef SkNoncopyable INHERITED;
155 template <typename T>
156 class GrTAllocator : SkNoncopyable {
158 virtual ~GrTAllocator() { this->reset(); };
161 * Create an allocator
163 * @param itemsPerBlock the number of items to allocate at once
165 explicit GrTAllocator(int itemsPerBlock)
166 : fAllocator(sizeof(T), itemsPerBlock, NULL) {}
169 * Adds an item and returns it.
171 * @return the added item.
174 void* item = fAllocator.push_back();
175 SkASSERT(NULL != item);
176 SkNEW_PLACEMENT(item, T);
180 T& push_back(const T& t) {
181 void* item = fAllocator.push_back();
182 SkASSERT(NULL != item);
183 SkNEW_PLACEMENT_ARGS(item, T, (t));
188 * removes all added items
191 int c = fAllocator.count();
192 for (int i = 0; i < c; ++i) {
193 ((T*)fAllocator[i])->~T();
202 return fAllocator.count();
208 bool empty() const { return fAllocator.empty(); }
211 * access last item, only call if count() != 0
214 return *(T*)fAllocator.back();
218 * access last item, only call if count() != 0
220 const T& back() const {
221 return *(const T*)fAllocator.back();
225 * access item by index.
227 T& operator[] (int i) {
228 return *(T*)(fAllocator[i]);
232 * access item by index.
234 const T& operator[] (int i) const {
235 return *(const T*)(fAllocator[i]);
240 * Set first block of memory to write into. Must be called before any other methods.
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.
246 void setInitialBlock(void* initialBlock) {
247 fAllocator.setInitialBlock(initialBlock);
251 GrAllocator fAllocator;
252 typedef SkNoncopyable INHERITED;
255 template <int N, typename T> class GrSTAllocator : public GrTAllocator<T> {
257 typedef GrTAllocator<T> INHERITED;
260 GrSTAllocator() : INHERITED(N) {
261 this->setInitialBlock(fStorage.get());
265 SkAlignedSTStorage<N, T> fStorage;