• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * 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.
7  */
8 
9 
10 
11 #ifndef GrAllocator_DEFINED
12 #define GrAllocator_DEFINED
13 
14 #include "GrConfig.h"
15 #include "SkTArray.h"
16 
17 class GrAllocator : GrNoncopyable {
18 public:
~GrAllocator()19     ~GrAllocator() {
20         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      */
GrAllocator(size_t itemSize,int itemsPerBlock,void * initialBlock)32     GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock) :
33             fItemSize(itemSize),
34             fItemsPerBlock(itemsPerBlock),
35             fOwnFirstBlock(NULL == initialBlock),
36             fCount(0) {
37         GrAssert(itemsPerBlock > 0);
38         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      */
push_back()48     void* push_back() {
49         int indexInBlock = fCount % fItemsPerBlock;
50         // 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      */
reset()67     void reset() {
68         int blockCount = GrMax((unsigned)1,
69                                GrUIDivRoundUp(fCount, fItemsPerBlock));
70         for (int i = 1; i < blockCount; ++i) {
71             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      */
count()84     int count() const {
85         return fCount;
86     }
87 
88     /**
89      * is the count 0
90      */
empty()91     bool empty() const { return fCount == 0; }
92 
93     /**
94      * access last item, only call if count() != 0
95      */
back()96     void* back() {
97         GrAssert(fCount);
98         return (*this)[fCount-1];
99     }
100 
101     /**
102      * access last item, only call if count() != 0
103      */
back()104     const void* back() const {
105         GrAssert(fCount);
106         return (*this)[fCount-1];
107     }
108 
109     /**
110      * access item by index.
111      */
112     void* operator[] (int i) {
113         GrAssert(i >= 0 && i < fCount);
114         return (char*)fBlocks[i / fItemsPerBlock] +
115                fItemSize * (i % fItemsPerBlock);
116     }
117 
118     /**
119      * access item by index.
120      */
121     const void* operator[] (int i) const {
122         GrAssert(i >= 0 && i < fCount);
123         return (const char*)fBlocks[i / fItemsPerBlock] +
124                fItemSize * (i % fItemsPerBlock);
125     }
126 
127 private:
128     static const int NUM_INIT_BLOCK_PTRS = 8;
129 
130     SkSTArray<NUM_INIT_BLOCK_PTRS, void*>   fBlocks;
131     size_t                                  fBlockSize;
132     size_t                                  fItemSize;
133     int                                     fItemsPerBlock;
134     bool                                    fOwnFirstBlock;
135     int                                     fCount;
136 
137     typedef GrNoncopyable INHERITED;
138 };
139 
140 template <typename T>
141 class GrTAllocator : GrNoncopyable {
142 
143 public:
~GrTAllocator()144     virtual ~GrTAllocator() { this->reset(); };
145 
146     /**
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      */
GrTAllocator(int itemsPerBlock)154     explicit GrTAllocator(int itemsPerBlock)
155         : fAllocator(sizeof(T), itemsPerBlock, NULL) {}
156 
157     /**
158      * Adds an item and returns it.
159      *
160      * @return the added item.
161      */
push_back()162     T& push_back() {
163         void* item = fAllocator.push_back();
164         GrAssert(NULL != item);
165         new (item) T;
166         return *(T*)item;
167     }
168 
push_back(const T & t)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 
176     /**
177      * removes all added items
178      */
reset()179     void reset() {
180         int c = fAllocator.count();
181         for (int i = 0; i < c; ++i) {
182             ((T*)fAllocator[i])->~T();
183         }
184         fAllocator.reset();
185     }
186 
187     /**
188      * count of items
189      */
count()190     int count() const {
191         return fAllocator.count();
192     }
193 
194     /**
195      * is the count 0
196      */
empty()197     bool empty() const { return fAllocator.empty(); }
198 
199     /**
200      * access last item, only call if count() != 0
201      */
back()202     T& back() {
203         return *(T*)fAllocator.back();
204     }
205 
206     /**
207      * access last item, only call if count() != 0
208      */
back()209     const T& back() const {
210         return *(const T*)fAllocator.back();
211     }
212 
213     /**
214      * access item by index.
215      */
216     T& operator[] (int i) {
217         return *(T*)(fAllocator[i]);
218     }
219 
220     /**
221      * access item by index.
222      */
223     const T& operator[] (int i) const {
224         return *(const T*)(fAllocator[i]);
225     }
226 
227 protected:
GrTAllocator(int itemsPerBlock,void * initialBlock)228     GrTAllocator(int itemsPerBlock, void* initialBlock)
229         : fAllocator(sizeof(T), itemsPerBlock, initialBlock) {
230     }
231 
232 private:
233     GrAllocator fAllocator;
234     typedef GrNoncopyable INHERITED;
235 };
236 
237 template <int N, typename T> class GrSTAllocator : public GrTAllocator<T> {
238 private:
239     typedef GrTAllocator<T> INHERITED;
240 
241 public:
GrSTAllocator()242     GrSTAllocator() : INHERITED(N, fStorage.get()) {
243     }
244 
245 private:
246     SkAlignedSTStorage<N, T> fStorage;
247 };
248 
249 #endif
250