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 : public 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 * Adds an item and returns pointer to it.
45 * @return pointer to the added item.
48 int indexInBlock = fCount % fItemsPerBlock;
49 // we always have at least one block
50 if (0 == indexInBlock) {
52 fBlocks.push_back() = sk_malloc_throw(fBlockSize);
53 } else if (fOwnFirstBlock) {
54 fBlocks[0] = sk_malloc_throw(fBlockSize);
57 void* ret = (char*)fBlocks[fCount/fItemsPerBlock] +
58 fItemSize * indexInBlock;
64 * removes all added items
67 int blockCount = GrMax((unsigned)1,
68 GrUIDivRoundUp(fCount, fItemsPerBlock));
69 for (int i = 1; i < blockCount; ++i) {
76 fBlocks.pop_back_n(blockCount-1);
90 bool empty() const { return fCount == 0; }
93 * access last item, only call if count() != 0
97 return (*this)[fCount-1];
101 * access last item, only call if count() != 0
103 const void* back() const {
105 return (*this)[fCount-1];
109 * access item by index.
111 void* operator[] (int i) {
112 SkASSERT(i >= 0 && i < fCount);
113 return (char*)fBlocks[i / fItemsPerBlock] +
114 fItemSize * (i % fItemsPerBlock);
118 * access item by index.
120 const void* operator[] (int i) const {
121 SkASSERT(i >= 0 && i < fCount);
122 return (const char*)fBlocks[i / fItemsPerBlock] +
123 fItemSize * (i % fItemsPerBlock);
127 static const int NUM_INIT_BLOCK_PTRS = 8;
129 SkSTArray<NUM_INIT_BLOCK_PTRS, void*> fBlocks;
136 typedef SkNoncopyable INHERITED;
139 template <typename T>
140 class GrTAllocator : public SkNoncopyable {
142 virtual ~GrTAllocator() { this->reset(); };
145 * Create an allocator
147 * @param itemsPerBlock the number of items to allocate at once
148 * @param initialBlock optional memory to use for the first block.
149 * Must be at least size(T)*itemsPerBlock sized.
150 * Caller is responsible for freeing this memory.
152 explicit GrTAllocator(int itemsPerBlock)
153 : fAllocator(sizeof(T), itemsPerBlock, NULL) {}
156 * Adds an item and returns it.
158 * @return the added item.
161 void* item = fAllocator.push_back();
162 SkASSERT(NULL != item);
163 SkNEW_PLACEMENT(item, T);
167 T& push_back(const T& t) {
168 void* item = fAllocator.push_back();
169 SkASSERT(NULL != item);
170 SkNEW_PLACEMENT_ARGS(item, T, (t));
175 * removes all added items
178 int c = fAllocator.count();
179 for (int i = 0; i < c; ++i) {
180 ((T*)fAllocator[i])->~T();
189 return fAllocator.count();
195 bool empty() const { return fAllocator.empty(); }
198 * access last item, only call if count() != 0
201 return *(T*)fAllocator.back();
205 * access last item, only call if count() != 0
207 const T& back() const {
208 return *(const T*)fAllocator.back();
212 * access item by index.
214 T& operator[] (int i) {
215 return *(T*)(fAllocator[i]);
219 * access item by index.
221 const T& operator[] (int i) const {
222 return *(const T*)(fAllocator[i]);
226 GrTAllocator(int itemsPerBlock, void* initialBlock)
227 : fAllocator(sizeof(T), itemsPerBlock, initialBlock) {
231 GrAllocator fAllocator;
232 typedef SkNoncopyable INHERITED;
235 template <int N, typename T> class GrSTAllocator : public GrTAllocator<T> {
237 typedef GrTAllocator<T> INHERITED;
240 GrSTAllocator() : INHERITED(N, fStorage.get()) {
244 SkAlignedSTStorage<N, T> fStorage;