blob: 57ca03cd329cf520d178920778da6953e7acedbd [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2010 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@google.comac10a2d2010-12-22 21:39:39 +00006 */
7
reed@google.comac10a2d2010-12-22 21:39:39 +00008#ifndef GrAllocator_DEFINED
9#define GrAllocator_DEFINED
10
11#include "GrConfig.h"
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +000012#include "GrTypes.h"
bsalomon@google.com49313f62011-09-14 13:54:05 +000013#include "SkTArray.h"
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +000014#include "SkTypes.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000015
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +000016class GrAllocator : public SkNoncopyable {
reed@google.comac10a2d2010-12-22 21:39:39 +000017public:
bsalomon@google.com4b90c622011-09-28 17:52:15 +000018 ~GrAllocator() {
reed@google.comac10a2d2010-12-22 21:39:39 +000019 reset();
20 }
21
22 /**
23 * Create an allocator
24 *
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.
30 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +000031 GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock) :
reed@google.comac10a2d2010-12-22 21:39:39 +000032 fItemSize(itemSize),
33 fItemsPerBlock(itemsPerBlock),
34 fOwnFirstBlock(NULL == initialBlock),
35 fCount(0) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000036 SkASSERT(itemsPerBlock > 0);
reed@google.comac10a2d2010-12-22 21:39:39 +000037 fBlockSize = fItemSize * fItemsPerBlock;
38 fBlocks.push_back() = initialBlock;
commit-bot@chromium.org1acc3d72013-09-06 23:13:05 +000039 SkDEBUGCODE(if (!fOwnFirstBlock) {*((char*)initialBlock+fBlockSize-1)='a';} );
reed@google.comac10a2d2010-12-22 21:39:39 +000040 }
41
42 /**
43 * Adds an item and returns pointer to it.
44 *
45 * @return pointer to the added item.
46 */
bsalomon@google.com4fa66942011-09-20 19:06:12 +000047 void* push_back() {
bsalomon@google.com6a77cc52011-04-28 17:33:34 +000048 int indexInBlock = fCount % fItemsPerBlock;
reed@google.comac10a2d2010-12-22 21:39:39 +000049 // we always have at least one block
50 if (0 == indexInBlock) {
51 if (0 != fCount) {
52 fBlocks.push_back() = GrMalloc(fBlockSize);
53 } else if (fOwnFirstBlock) {
54 fBlocks[0] = GrMalloc(fBlockSize);
55 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000056 }
57 void* ret = (char*)fBlocks[fCount/fItemsPerBlock] +
reed@google.comac10a2d2010-12-22 21:39:39 +000058 fItemSize * indexInBlock;
59 ++fCount;
60 return ret;
61 }
62
63 /**
64 * removes all added items
65 */
rmistry@google.comd6176b02012-08-23 18:14:13 +000066 void reset() {
67 int blockCount = GrMax((unsigned)1,
bsalomon@google.com6a77cc52011-04-28 17:33:34 +000068 GrUIDivRoundUp(fCount, fItemsPerBlock));
69 for (int i = 1; i < blockCount; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +000070 GrFree(fBlocks[i]);
71 }
72 if (fOwnFirstBlock) {
73 GrFree(fBlocks[0]);
74 fBlocks[0] = NULL;
75 }
76 fBlocks.pop_back_n(blockCount-1);
77 fCount = 0;
78 }
79
80 /**
81 * count of items
82 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +000083 int count() const {
reed@google.comac10a2d2010-12-22 21:39:39 +000084 return fCount;
85 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000086
reed@google.comac10a2d2010-12-22 21:39:39 +000087 /**
88 * is the count 0
89 */
90 bool empty() const { return fCount == 0; }
rmistry@google.comd6176b02012-08-23 18:14:13 +000091
reed@google.comac10a2d2010-12-22 21:39:39 +000092 /**
93 * access last item, only call if count() != 0
94 */
95 void* back() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000096 SkASSERT(fCount);
reed@google.comac10a2d2010-12-22 21:39:39 +000097 return (*this)[fCount-1];
98 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000099
reed@google.comac10a2d2010-12-22 21:39:39 +0000100 /**
101 * access last item, only call if count() != 0
102 */
103 const void* back() const {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000104 SkASSERT(fCount);
reed@google.comac10a2d2010-12-22 21:39:39 +0000105 return (*this)[fCount-1];
106 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000107
reed@google.comac10a2d2010-12-22 21:39:39 +0000108 /**
109 * access item by index.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000110 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000111 void* operator[] (int i) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000112 SkASSERT(i >= 0 && i < fCount);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000113 return (char*)fBlocks[i / fItemsPerBlock] +
reed@google.comac10a2d2010-12-22 21:39:39 +0000114 fItemSize * (i % fItemsPerBlock);
115 }
116
117 /**
118 * access item by index.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000119 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000120 const void* operator[] (int i) const {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000121 SkASSERT(i >= 0 && i < fCount);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000122 return (const char*)fBlocks[i / fItemsPerBlock] +
reed@google.comac10a2d2010-12-22 21:39:39 +0000123 fItemSize * (i % fItemsPerBlock);
124 }
125
126private:
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000127 static const int NUM_INIT_BLOCK_PTRS = 8;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000128
bsalomon@google.com92669012011-09-27 19:10:05 +0000129 SkSTArray<NUM_INIT_BLOCK_PTRS, void*> fBlocks;
130 size_t fBlockSize;
131 size_t fItemSize;
132 int fItemsPerBlock;
133 bool fOwnFirstBlock;
134 int fCount;
bsalomon@google.com4b90c622011-09-28 17:52:15 +0000135
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000136 typedef SkNoncopyable INHERITED;
reed@google.comac10a2d2010-12-22 21:39:39 +0000137};
138
139template <typename T>
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000140class GrTAllocator : public SkNoncopyable {
reed@google.comac10a2d2010-12-22 21:39:39 +0000141public:
bsalomon@google.com13788bf2011-10-27 17:17:44 +0000142 virtual ~GrTAllocator() { this->reset(); };
bsalomon@google.coma55847b2011-04-20 15:47:04 +0000143
reed@google.comac10a2d2010-12-22 21:39:39 +0000144 /**
145 * Create an allocator
146 *
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.
151 */
bsalomon@google.com4b90c622011-09-28 17:52:15 +0000152 explicit GrTAllocator(int itemsPerBlock)
153 : fAllocator(sizeof(T), itemsPerBlock, NULL) {}
bsalomon@google.coma55847b2011-04-20 15:47:04 +0000154
155 /**
reed@google.comac10a2d2010-12-22 21:39:39 +0000156 * Adds an item and returns it.
157 *
158 * @return the added item.
159 */
160 T& push_back() {
161 void* item = fAllocator.push_back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000162 SkASSERT(NULL != item);
tomhudson@google.comc377baf2012-07-09 20:17:56 +0000163 SkNEW_PLACEMENT(item, T);
reed@google.comac10a2d2010-12-22 21:39:39 +0000164 return *(T*)item;
165 }
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000166
167 T& push_back(const T& t) {
168 void* item = fAllocator.push_back();
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000169 SkASSERT(NULL != item);
tomhudson@google.comc377baf2012-07-09 20:17:56 +0000170 SkNEW_PLACEMENT_ARGS(item, T, (t));
bsalomon@google.com4fa66942011-09-20 19:06:12 +0000171 return *(T*)item;
172 }
173
reed@google.comac10a2d2010-12-22 21:39:39 +0000174 /**
175 * removes all added items
176 */
177 void reset() {
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000178 int c = fAllocator.count();
179 for (int i = 0; i < c; ++i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000180 ((T*)fAllocator[i])->~T();
181 }
182 fAllocator.reset();
183 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000184
reed@google.comac10a2d2010-12-22 21:39:39 +0000185 /**
186 * count of items
187 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000188 int count() const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000189 return fAllocator.count();
190 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000191
reed@google.comac10a2d2010-12-22 21:39:39 +0000192 /**
193 * is the count 0
194 */
195 bool empty() const { return fAllocator.empty(); }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000196
reed@google.comac10a2d2010-12-22 21:39:39 +0000197 /**
198 * access last item, only call if count() != 0
199 */
200 T& back() {
201 return *(T*)fAllocator.back();
202 }
203
204 /**
205 * access last item, only call if count() != 0
206 */
207 const T& back() const {
208 return *(const T*)fAllocator.back();
209 }
210
211 /**
212 * access item by index.
rmistry@google.comd6176b02012-08-23 18:14:13 +0000213 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000214 T& operator[] (int i) {
reed@google.comac10a2d2010-12-22 21:39:39 +0000215 return *(T*)(fAllocator[i]);
216 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000217
reed@google.comac10a2d2010-12-22 21:39:39 +0000218 /**
219 * access item by index.
220 */
bsalomon@google.com6a77cc52011-04-28 17:33:34 +0000221 const T& operator[] (int i) const {
reed@google.comac10a2d2010-12-22 21:39:39 +0000222 return *(const T*)(fAllocator[i]);
bsalomon@google.com4b90c622011-09-28 17:52:15 +0000223 }
224
225protected:
226 GrTAllocator(int itemsPerBlock, void* initialBlock)
227 : fAllocator(sizeof(T), itemsPerBlock, initialBlock) {
228 }
229
230private:
231 GrAllocator fAllocator;
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000232 typedef SkNoncopyable INHERITED;
bsalomon@google.com4b90c622011-09-28 17:52:15 +0000233};
234
235template <int N, typename T> class GrSTAllocator : public GrTAllocator<T> {
236private:
237 typedef GrTAllocator<T> INHERITED;
238
239public:
240 GrSTAllocator() : INHERITED(N, fStorage.get()) {
241 }
242
243private:
244 SkAlignedSTStorage<N, T> fStorage;
reed@google.comac10a2d2010-12-22 21:39:39 +0000245};
246
247#endif