blob: da02ba40b014cfeeef10b2fdbdb6581ae9c7a051 [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;
138 size_t fBlockSize;
139 char fBlockInitialStorage[NUM_INIT_BLOCK_PTRS*sizeof(void*)];
140 size_t fItemSize;
141 uint32_t fItemsPerBlock;
142 bool fOwnFirstBlock;
143 uint32_t fCount;
144};
145
146template <typename T>
147class GrTAllocator {
148private:
149 GrAllocator fAllocator;
150
151public:
152 virtual ~GrTAllocator() {};
153
154 /**
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 */
162 GrTAllocator(uint32_t itemsPerBlock, void* initialBlock) :
163 fAllocator(sizeof(T), itemsPerBlock, initialBlock)
164 {}
165
166 /**
167 * Adds an item and returns it.
168 *
169 * @return the added item.
170 */
171 T& push_back() {
172 void* item = fAllocator.push_back();
173 GrAssert(NULL != item);
174 new (item) T;
175 return *(T*)item;
176 }
177
178 /**
179 * removes all added items
180 */
181 void reset() {
182 uint32_t c = fAllocator.count();
183 for (uint32_t i = 0; i < c; ++i) {
184 ((T*)fAllocator[i])->~T();
185 }
186 fAllocator.reset();
187 }
188
189 /**
190 * count of items
191 */
192 uint32_t count() const {
193 return fAllocator.count();
194 }
195
196 /**
197 * is the count 0
198 */
199 bool empty() const { return fAllocator.empty(); }
200
201 /**
202 * access last item, only call if count() != 0
203 */
204 T& back() {
205 return *(T*)fAllocator.back();
206 }
207
208 /**
209 * access last item, only call if count() != 0
210 */
211 const T& back() const {
212 return *(const T*)fAllocator.back();
213 }
214
215 /**
216 * access item by index.
217 */
218 T& operator[] (uint32_t i) {
219 return *(T*)(fAllocator[i]);
220 }
221
222 /**
223 * access item by index.
224 */
225 const T& operator[] (uint32_t i) const {
226 return *(const T*)(fAllocator[i]);
227 }
228};
229
230#endif