blob: f333d42e3745e004d0663e494d02b2c11a2080e6 [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
tomhudson@google.com168e6342012-04-18 17:49:20 +000014#include "GrNoncopyable.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000015#include "GrConfig.h"
bsalomon@google.com49313f62011-09-14 13:54:05 +000016#include "SkTArray.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000017
bsalomon@google.com4b90c622011-09-28 17:52:15 +000018class GrAllocator : GrNoncopyable {
reed@google.comac10a2d2010-12-22 21:39:39 +000019public:
bsalomon@google.com4b90c622011-09-28 17:52:15 +000020 ~GrAllocator() {
reed@google.comac10a2d2010-12-22 21:39:39 +000021 reset();
22 }
23
24 /**
25 * Create an allocator
26 *
27 * @param itemSize the size of each item to allocate
28 * @param itemsPerBlock the number of items to allocate at once
29 * @param initialBlock optional memory to use for the first block.
30 * Must be at least itemSize*itemsPerBlock sized.
31 * Caller is responsible for freeing this memory.
32 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +000033 GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock) :
reed@google.comac10a2d2010-12-22 21:39:39 +000034 fItemSize(itemSize),
35 fItemsPerBlock(itemsPerBlock),
36 fOwnFirstBlock(NULL == initialBlock),
37 fCount(0) {
bsalomon@google.com6a77cc52011-04-28 17:33:34 +000038 GrAssert(itemsPerBlock > 0);
reed@google.comac10a2d2010-12-22 21:39:39 +000039 fBlockSize = fItemSize * fItemsPerBlock;
40 fBlocks.push_back() = initialBlock;
41 GR_DEBUGCODE(if (!fOwnFirstBlock) {*((char*)initialBlock+fBlockSize-1)='a';} );
42 }
43
44 /**
45 * Adds an item and returns pointer to it.
46 *
47 * @return pointer to the added item.
48 */
bsalomon@google.com4fa66942011-09-20 19:06:12 +000049 void* push_back() {
bsalomon@google.com6a77cc52011-04-28 17:33:34 +000050 int indexInBlock = fCount % fItemsPerBlock;
reed@google.comac10a2d2010-12-22 21:39:39 +000051 // we always have at least one block
52 if (0 == indexInBlock) {
53 if (0 != fCount) {
54 fBlocks.push_back() = GrMalloc(fBlockSize);
55 } else if (fOwnFirstBlock) {
56 fBlocks[0] = GrMalloc(fBlockSize);
57 }
58 }
59 void* ret = (char*)fBlocks[fCount/fItemsPerBlock] +
60 fItemSize * indexInBlock;
61 ++fCount;
62 return ret;
63 }
64
65 /**
66 * removes all added items
67 */
68 void reset() {
bsalomon@google.com6a77cc52011-04-28 17:33:34 +000069 int blockCount = GrMax((unsigned)1,
70 GrUIDivRoundUp(fCount, fItemsPerBlock));
71 for (int i = 1; i < blockCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +000072 GrFree(fBlocks[i]);
73 }
74 if (fOwnFirstBlock) {
75 GrFree(fBlocks[0]);
76 fBlocks[0] = NULL;
77 }
78 fBlocks.pop_back_n(blockCount-1);
79 fCount = 0;
80 }
81
82 /**
83 * count of items
84 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +000085 int count() const {
reed@google.comac10a2d2010-12-22 21:39:39 +000086 return fCount;
87 }
88
89 /**
90 * is the count 0
91 */
92 bool empty() const { return fCount == 0; }
93
94 /**
95 * access last item, only call if count() != 0
96 */
97 void* back() {
98 GrAssert(fCount);
99 return (*this)[fCount-1];
100 }
101
102 /**
103 * access last item, only call if count() != 0
104 */
105 const void* back() const {
106 GrAssert(fCount);
107 return (*this)[fCount-1];
108 }
109
110 /**
111 * access item by index.
112 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000113 void* operator[] (int i) {
114 GrAssert(i >= 0 && i < fCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000115 return (char*)fBlocks[i / fItemsPerBlock] +
116 fItemSize * (i % fItemsPerBlock);
117 }
118
119 /**
120 * access item by index.
121 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000122 const void* operator[] (int i) const {
123 GrAssert(i >= 0 && i < fCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000124 return (const char*)fBlocks[i / fItemsPerBlock] +
125 fItemSize * (i % fItemsPerBlock);
126 }
127
128private:
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000129 static const int NUM_INIT_BLOCK_PTRS = 8;
reed@google.comac10a2d2010-12-22 21:39:39 +0000130
bsalomon@google.com92669012011-09-27 19:10:05 +0000131 SkSTArray<NUM_INIT_BLOCK_PTRS, void*> fBlocks;
132 size_t fBlockSize;
133 size_t fItemSize;
134 int fItemsPerBlock;
135 bool fOwnFirstBlock;
136 int fCount;
bsalomon@google.com4b90c622011-09-28 17:52:15 +0000137
138 typedef GrNoncopyable INHERITED;
reed@google.comac10a2d2010-12-22 21:39:39 +0000139};
140
141template <typename T>
bsalomon@google.com4b90c622011-09-28 17:52:15 +0000142class GrTAllocator : GrNoncopyable {
143
reed@google.comac10a2d2010-12-22 21:39:39 +0000144public:
bsalomon@google.com13788bf2011-10-27 17:17:44 +0000145 virtual ~GrTAllocator() { this->reset(); };
bsalomon@google.coma55847b2011-04-20 15:47:04 +0000146
reed@google.comac10a2d2010-12-22 21:39:39 +0000147 /**
148 * Create an allocator
149 *
150 * @param itemsPerBlock the number of items to allocate at once
151 * @param initialBlock optional memory to use for the first block.
152 * Must be at least size(T)*itemsPerBlock sized.
153 * Caller is responsible for freeing this memory.
154 */
bsalomon@google.com4b90c622011-09-28 17:52:15 +0000155 explicit GrTAllocator(int itemsPerBlock)
156 : fAllocator(sizeof(T), itemsPerBlock, NULL) {}
bsalomon@google.coma55847b2011-04-20 15:47:04 +0000157
158 /**
reed@google.comac10a2d2010-12-22 21:39:39 +0000159 * Adds an item and returns it.
160 *
161 * @return the added item.
162 */
163 T& push_back() {
164 void* item = fAllocator.push_back();
165 GrAssert(NULL != item);
166 new (item) T;
167 return *(T*)item;
168 }
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000169
170 T& push_back(const T& t) {
171 void* item = fAllocator.push_back();
172 GrAssert(NULL != item);
173 new (item) T(t);
174 return *(T*)item;
175 }
176
reed@google.comac10a2d2010-12-22 21:39:39 +0000177 /**
178 * removes all added items
179 */
180 void reset() {
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000181 int c = fAllocator.count();
182 for (int i = 0; i < c; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000183 ((T*)fAllocator[i])->~T();
184 }
185 fAllocator.reset();
186 }
187
188 /**
189 * count of items
190 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000191 int count() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000192 return fAllocator.count();
193 }
194
195 /**
196 * is the count 0
197 */
198 bool empty() const { return fAllocator.empty(); }
199
200 /**
201 * access last item, only call if count() != 0
202 */
203 T& back() {
204 return *(T*)fAllocator.back();
205 }
206
207 /**
208 * access last item, only call if count() != 0
209 */
210 const T& back() const {
211 return *(const T*)fAllocator.back();
212 }
213
214 /**
215 * access item by index.
216 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000217 T& operator[] (int i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000218 return *(T*)(fAllocator[i]);
219 }
220
221 /**
222 * access item by index.
223 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000224 const T& operator[] (int i) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000225 return *(const T*)(fAllocator[i]);
bsalomon@google.com4b90c622011-09-28 17:52:15 +0000226 }
227
228protected:
229 GrTAllocator(int itemsPerBlock, void* initialBlock)
230 : fAllocator(sizeof(T), itemsPerBlock, initialBlock) {
231 }
232
233private:
234 GrAllocator fAllocator;
235 typedef GrNoncopyable INHERITED;
236};
237
238template <int N, typename T> class GrSTAllocator : public GrTAllocator<T> {
239private:
240 typedef GrTAllocator<T> INHERITED;
241
242public:
243 GrSTAllocator() : INHERITED(N, fStorage.get()) {
244 }
245
246private:
247 SkAlignedSTStorage<N, T> fStorage;
reed@google.comac10a2d2010-12-22 21:39:39 +0000248};
249
250#endif