blob: 28a18bf834408184c4626f234f6be882cd327c06 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
2 Copyright 2010 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#ifndef GrAllocator_DEFINED
19#define GrAllocator_DEFINED
20
21#include "GrConfig.h"
22#include "GrTArray.h"
23
24class GrAllocator {
25public:
26 virtual ~GrAllocator() {
27 reset();
28 }
29
30 /**
31 * Create an allocator
32 *
33 * @param itemSize the size of each item to allocate
34 * @param itemsPerBlock the number of items to allocate at once
35 * @param initialBlock optional memory to use for the first block.
36 * Must be at least itemSize*itemsPerBlock sized.
37 * Caller is responsible for freeing this memory.
38 */
39 GrAllocator(size_t itemSize, uint32_t itemsPerBlock, void* initialBlock) :
40 fBlocks(fBlockInitialStorage, NUM_INIT_BLOCK_PTRS),
41 fItemSize(itemSize),
42 fItemsPerBlock(itemsPerBlock),
43 fOwnFirstBlock(NULL == initialBlock),
44 fCount(0) {
45 fBlockSize = fItemSize * fItemsPerBlock;
46 fBlocks.push_back() = initialBlock;
47 GR_DEBUGCODE(if (!fOwnFirstBlock) {*((char*)initialBlock+fBlockSize-1)='a';} );
48 }
49
50 /**
51 * Adds an item and returns pointer to it.
52 *
53 * @return pointer to the added item.
54 */
55 void* push_back() {
56 uint32_t indexInBlock = fCount % fItemsPerBlock;
57 // we always have at least one block
58 if (0 == indexInBlock) {
59 if (0 != fCount) {
60 fBlocks.push_back() = GrMalloc(fBlockSize);
61 } else if (fOwnFirstBlock) {
62 fBlocks[0] = GrMalloc(fBlockSize);
63 }
64 }
65 void* ret = (char*)fBlocks[fCount/fItemsPerBlock] +
66 fItemSize * indexInBlock;
67 ++fCount;
68 return ret;
69 }
70
71 /**
72 * removes all added items
73 */
74 void reset() {
75 uint32_t blockCount = GrMax((unsigned)1,
76 GrUIDivRoundUp(fCount, fItemsPerBlock));
77 for (uint32_t i = 1; i < blockCount; ++i) {
78 GrFree(fBlocks[i]);
79 }
80 if (fOwnFirstBlock) {
81 GrFree(fBlocks[0]);
82 fBlocks[0] = NULL;
83 }
84 fBlocks.pop_back_n(blockCount-1);
85 fCount = 0;
86 }
87
88 /**
89 * count of items
90 */
91 uint32_t count() const {
92 return fCount;
93 }
94
95 /**
96 * is the count 0
97 */
98 bool empty() const { return fCount == 0; }
99
100 /**
101 * access last item, only call if count() != 0
102 */
103 void* back() {
104 GrAssert(fCount);
105 return (*this)[fCount-1];
106 }
107
108 /**
109 * access last item, only call if count() != 0
110 */
111 const void* back() const {
112 GrAssert(fCount);
113 return (*this)[fCount-1];
114 }
115
116 /**
117 * access item by index.
118 */
119 void* operator[] (uint32_t i) {
120 GrAssert(i < fCount);
121 return (char*)fBlocks[i / fItemsPerBlock] +
122 fItemSize * (i % fItemsPerBlock);
123 }
124
125 /**
126 * access item by index.
127 */
128 const void* operator[] (uint32_t i) const {
129 GrAssert(i < fCount);
130 return (const char*)fBlocks[i / fItemsPerBlock] +
131 fItemSize * (i % fItemsPerBlock);
132 }
133
134private:
135 static const uint32_t NUM_INIT_BLOCK_PTRS = 8;
136
137 GrTArray<void*> fBlocks;
bsalomon@google.coma55847b2011-04-20 15:47:04 +0000138 size_t fBlockSize;
139 char fBlockInitialStorage[NUM_INIT_BLOCK_PTRS*sizeof(void*)];
reed@google.comac10a2d2010-12-22 21:39:39 +0000140 size_t fItemSize;
141 uint32_t fItemsPerBlock;
142 bool fOwnFirstBlock;
bsalomon@google.coma55847b2011-04-20 15:47:04 +0000143 uint32_t fCount;
reed@google.comac10a2d2010-12-22 21:39:39 +0000144};
145
146template <typename T>
147class GrTAllocator {
148private:
149 GrAllocator fAllocator;
150
151public:
152 virtual ~GrTAllocator() {};
bsalomon@google.coma55847b2011-04-20 15:47:04 +0000153
reed@google.comac10a2d2010-12-22 21:39:39 +0000154 /**
155 * Create an allocator
156 *
157 * @param itemsPerBlock the number of items to allocate at once
158 * @param initialBlock optional memory to use for the first block.
159 * Must be at least size(T)*itemsPerBlock sized.
160 * Caller is responsible for freeing this memory.
161 */
bsalomon@google.coma55847b2011-04-20 15:47:04 +0000162 GrTAllocator(uint32_t itemsPerBlock, void* initialBlock)
163 : fAllocator(sizeof(T), itemsPerBlock, initialBlock) {}
164
165 /**
166 * Create an allocator using a GrAlignedTAlloc as the initial block.
167 *
168 * @param initialBlock specifies the storage for the initial block
169 * and the size of subsequent blocks.
170 */
171 template <int N>
172 GrTAllocator(GrAlignedSTStorage<N,T>* initialBlock)
173 : fAllocator(sizeof(T), N, initialBlock->get()) {}
reed@google.comac10a2d2010-12-22 21:39:39 +0000174
175 /**
176 * Adds an item and returns it.
177 *
178 * @return the added item.
179 */
180 T& push_back() {
181 void* item = fAllocator.push_back();
182 GrAssert(NULL != item);
183 new (item) T;
184 return *(T*)item;
185 }
186
187 /**
188 * removes all added items
189 */
190 void reset() {
191 uint32_t c = fAllocator.count();
192 for (uint32_t i = 0; i < c; ++i) {
193 ((T*)fAllocator[i])->~T();
194 }
195 fAllocator.reset();
196 }
197
198 /**
199 * count of items
200 */
201 uint32_t 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[] (uint32_t i) {
228 return *(T*)(fAllocator[i]);
229 }
230
231 /**
232 * access item by index.
233 */
234 const T& operator[] (uint32_t i) const {
235 return *(const T*)(fAllocator[i]);
236 }
237};
238
239#endif