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