blob: 555e56ffc14c63f516f06016ea6abb60e23978f1 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * 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.
reed@google.comac10a2d2010-12-22 21:39:39 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
reed@google.comac10a2d2010-12-22 21:39:39 +000011#ifndef GrAllocator_DEFINED
12#define GrAllocator_DEFINED
13
14#include "GrConfig.h"
bsalomon@google.com49313f62011-09-14 13:54:05 +000015#include "SkTArray.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000016
bsalomon@google.com4b90c622011-09-28 17:52:15 +000017class GrAllocator : GrNoncopyable {
reed@google.comac10a2d2010-12-22 21:39:39 +000018public:
bsalomon@google.com4b90c622011-09-28 17:52:15 +000019 ~GrAllocator() {
reed@google.comac10a2d2010-12-22 21:39:39 +000020 reset();
21 }
22
23 /**
24 * Create an allocator
25 *
26 * @param itemSize the size of each item to allocate
27 * @param itemsPerBlock the number of items to allocate at once
28 * @param initialBlock optional memory to use for the first block.
29 * Must be at least itemSize*itemsPerBlock sized.
30 * Caller is responsible for freeing this memory.
31 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +000032 GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock) :
reed@google.comac10a2d2010-12-22 21:39:39 +000033 fItemSize(itemSize),
34 fItemsPerBlock(itemsPerBlock),
35 fOwnFirstBlock(NULL == initialBlock),
36 fCount(0) {
bsalomon@google.com6a77cc52011-04-28 17:33:34 +000037 GrAssert(itemsPerBlock > 0);
reed@google.comac10a2d2010-12-22 21:39:39 +000038 fBlockSize = fItemSize * fItemsPerBlock;
39 fBlocks.push_back() = initialBlock;
40 GR_DEBUGCODE(if (!fOwnFirstBlock) {*((char*)initialBlock+fBlockSize-1)='a';} );
41 }
42
43 /**
44 * Adds an item and returns pointer to it.
45 *
46 * @return pointer to the added item.
47 */
bsalomon@google.com4fa66942011-09-20 19:06:12 +000048 void* push_back() {
bsalomon@google.com6a77cc52011-04-28 17:33:34 +000049 int indexInBlock = fCount % fItemsPerBlock;
reed@google.comac10a2d2010-12-22 21:39:39 +000050 // we always have at least one block
51 if (0 == indexInBlock) {
52 if (0 != fCount) {
53 fBlocks.push_back() = GrMalloc(fBlockSize);
54 } else if (fOwnFirstBlock) {
55 fBlocks[0] = GrMalloc(fBlockSize);
56 }
57 }
58 void* ret = (char*)fBlocks[fCount/fItemsPerBlock] +
59 fItemSize * indexInBlock;
60 ++fCount;
61 return ret;
62 }
63
64 /**
65 * removes all added items
66 */
67 void reset() {
bsalomon@google.com6a77cc52011-04-28 17:33:34 +000068 int blockCount = GrMax((unsigned)1,
69 GrUIDivRoundUp(fCount, fItemsPerBlock));
70 for (int i = 1; i < blockCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +000071 GrFree(fBlocks[i]);
72 }
73 if (fOwnFirstBlock) {
74 GrFree(fBlocks[0]);
75 fBlocks[0] = NULL;
76 }
77 fBlocks.pop_back_n(blockCount-1);
78 fCount = 0;
79 }
80
81 /**
82 * count of items
83 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +000084 int count() const {
reed@google.comac10a2d2010-12-22 21:39:39 +000085 return fCount;
86 }
87
88 /**
89 * is the count 0
90 */
91 bool empty() const { return fCount == 0; }
92
93 /**
94 * access last item, only call if count() != 0
95 */
96 void* back() {
97 GrAssert(fCount);
98 return (*this)[fCount-1];
99 }
100
101 /**
102 * access last item, only call if count() != 0
103 */
104 const void* back() const {
105 GrAssert(fCount);
106 return (*this)[fCount-1];
107 }
108
109 /**
110 * access item by index.
111 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000112 void* operator[] (int i) {
113 GrAssert(i >= 0 && i < fCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000114 return (char*)fBlocks[i / fItemsPerBlock] +
115 fItemSize * (i % fItemsPerBlock);
116 }
117
118 /**
119 * access item by index.
120 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000121 const void* operator[] (int i) const {
122 GrAssert(i >= 0 && i < fCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000123 return (const char*)fBlocks[i / fItemsPerBlock] +
124 fItemSize * (i % fItemsPerBlock);
125 }
126
127private:
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000128 static const int NUM_INIT_BLOCK_PTRS = 8;
reed@google.comac10a2d2010-12-22 21:39:39 +0000129
bsalomon@google.com92669012011-09-27 19:10:05 +0000130 SkSTArray<NUM_INIT_BLOCK_PTRS, void*> fBlocks;
131 size_t fBlockSize;
132 size_t fItemSize;
133 int fItemsPerBlock;
134 bool fOwnFirstBlock;
135 int fCount;
bsalomon@google.com4b90c622011-09-28 17:52:15 +0000136
137 typedef GrNoncopyable INHERITED;
reed@google.comac10a2d2010-12-22 21:39:39 +0000138};
139
140template <typename T>
bsalomon@google.com4b90c622011-09-28 17:52:15 +0000141class GrTAllocator : GrNoncopyable {
142
reed@google.comac10a2d2010-12-22 21:39:39 +0000143public:
bsalomon@google.com13788bf2011-10-27 17:17:44 +0000144 virtual ~GrTAllocator() { this->reset(); };
bsalomon@google.coma55847b2011-04-20 15:47:04 +0000145
reed@google.comac10a2d2010-12-22 21:39:39 +0000146 /**
147 * Create an allocator
148 *
149 * @param itemsPerBlock the number of items to allocate at once
150 * @param initialBlock optional memory to use for the first block.
151 * Must be at least size(T)*itemsPerBlock sized.
152 * Caller is responsible for freeing this memory.
153 */
bsalomon@google.com4b90c622011-09-28 17:52:15 +0000154 explicit GrTAllocator(int itemsPerBlock)
155 : fAllocator(sizeof(T), itemsPerBlock, NULL) {}
bsalomon@google.coma55847b2011-04-20 15:47:04 +0000156
157 /**
reed@google.comac10a2d2010-12-22 21:39:39 +0000158 * Adds an item and returns it.
159 *
160 * @return the added item.
161 */
162 T& push_back() {
163 void* item = fAllocator.push_back();
164 GrAssert(NULL != item);
165 new (item) T;
166 return *(T*)item;
167 }
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000168
169 T& push_back(const T& t) {
170 void* item = fAllocator.push_back();
171 GrAssert(NULL != item);
172 new (item) T(t);
173 return *(T*)item;
174 }
175
reed@google.comac10a2d2010-12-22 21:39:39 +0000176 /**
177 * removes all added items
178 */
179 void reset() {
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000180 int c = fAllocator.count();
181 for (int i = 0; i < c; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000182 ((T*)fAllocator[i])->~T();
183 }
184 fAllocator.reset();
185 }
186
187 /**
188 * count of items
189 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000190 int count() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000191 return fAllocator.count();
192 }
193
194 /**
195 * is the count 0
196 */
197 bool empty() const { return fAllocator.empty(); }
198
199 /**
200 * access last item, only call if count() != 0
201 */
202 T& back() {
203 return *(T*)fAllocator.back();
204 }
205
206 /**
207 * access last item, only call if count() != 0
208 */
209 const T& back() const {
210 return *(const T*)fAllocator.back();
211 }
212
213 /**
214 * access item by index.
215 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000216 T& operator[] (int i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000217 return *(T*)(fAllocator[i]);
218 }
219
220 /**
221 * access item by index.
222 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000223 const T& operator[] (int i) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000224 return *(const T*)(fAllocator[i]);
bsalomon@google.com4b90c622011-09-28 17:52:15 +0000225 }
226
227protected:
228 GrTAllocator(int itemsPerBlock, void* initialBlock)
229 : fAllocator(sizeof(T), itemsPerBlock, initialBlock) {
230 }
231
232private:
233 GrAllocator fAllocator;
234 typedef GrNoncopyable INHERITED;
235};
236
237template <int N, typename T> class GrSTAllocator : public GrTAllocator<T> {
238private:
239 typedef GrTAllocator<T> INHERITED;
240
241public:
242 GrSTAllocator() : INHERITED(N, fStorage.get()) {
243 }
244
245private:
246 SkAlignedSTStorage<N, T> fStorage;
reed@google.comac10a2d2010-12-22 21:39:39 +0000247};
248
249#endif