• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     Copyright 2010 Google Inc.
3 
4     Licensed under the Apache License, Version 2.0 (the "License");
5     you may not use this file except in compliance with the License.
6     You may obtain a copy of the License at
7 
8          http://www.apache.org/licenses/LICENSE-2.0
9 
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15  */
16 
17 
18 #ifndef GrAllocator_DEFINED
19 #define GrAllocator_DEFINED
20 
21 #include "GrConfig.h"
22 #include "GrTArray.h"
23 
24 class GrAllocator {
25 public:
~GrAllocator()26     virtual ~GrAllocator() {
27         reset();
28     }
29 
30     /**
31      * Create an allocator
32      *
33      * @param   itemSize        the size of each item to allocate
34      * @param   itemsPerBlock   the number of items to allocate at once
35      * @param   initialBlock    optional memory to use for the first block.
36      *                          Must be at least itemSize*itemsPerBlock sized.
37      *                          Caller is responsible for freeing this memory.
38      */
GrAllocator(size_t itemSize,int itemsPerBlock,void * initialBlock)39     GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock) :
40             fBlocks(fBlockInitialStorage, NUM_INIT_BLOCK_PTRS),
41             fItemSize(itemSize),
42             fItemsPerBlock(itemsPerBlock),
43             fOwnFirstBlock(NULL == initialBlock),
44             fCount(0) {
45         GrAssert(itemsPerBlock > 0);
46         fBlockSize = fItemSize * fItemsPerBlock;
47         fBlocks.push_back() = initialBlock;
48         GR_DEBUGCODE(if (!fOwnFirstBlock) {*((char*)initialBlock+fBlockSize-1)='a';} );
49     }
50 
51     /**
52      * Adds an item and returns pointer to it.
53      *
54      * @return pointer to the added item.
55      */
push_back()56     void* push_back() {
57         int indexInBlock = fCount % fItemsPerBlock;
58         // we always have at least one block
59         if (0 == indexInBlock) {
60             if (0 != fCount) {
61                 fBlocks.push_back() = GrMalloc(fBlockSize);
62             } else if (fOwnFirstBlock) {
63                 fBlocks[0] = GrMalloc(fBlockSize);
64             }
65         }
66         void* ret = (char*)fBlocks[fCount/fItemsPerBlock] +
67                     fItemSize * indexInBlock;
68         ++fCount;
69         return ret;
70     }
71 
72     /**
73      * removes all added items
74      */
reset()75     void reset() {
76         int blockCount = GrMax((unsigned)1,
77                                GrUIDivRoundUp(fCount, fItemsPerBlock));
78         for (int i = 1; i < blockCount; ++i) {
79             GrFree(fBlocks[i]);
80         }
81         if (fOwnFirstBlock) {
82             GrFree(fBlocks[0]);
83             fBlocks[0] = NULL;
84         }
85         fBlocks.pop_back_n(blockCount-1);
86         fCount = 0;
87     }
88 
89     /**
90      * count of items
91      */
count()92     int count() const {
93         return fCount;
94     }
95 
96     /**
97      * is the count 0
98      */
empty()99     bool empty() const { return fCount == 0; }
100 
101     /**
102      * access last item, only call if count() != 0
103      */
back()104     void* back() {
105         GrAssert(fCount);
106         return (*this)[fCount-1];
107     }
108 
109     /**
110      * access last item, only call if count() != 0
111      */
back()112     const void* back() const {
113         GrAssert(fCount);
114         return (*this)[fCount-1];
115     }
116 
117     /**
118      * access item by index.
119      */
120     void* operator[] (int i) {
121         GrAssert(i >= 0 && i < fCount);
122         return (char*)fBlocks[i / fItemsPerBlock] +
123                fItemSize * (i % fItemsPerBlock);
124     }
125 
126     /**
127      * access item by index.
128      */
129     const void* operator[] (int i) const {
130         GrAssert(i >= 0 && i < fCount);
131         return (const char*)fBlocks[i / fItemsPerBlock] +
132                fItemSize * (i % fItemsPerBlock);
133     }
134 
135 private:
136     static const int NUM_INIT_BLOCK_PTRS = 8;
137 
138     GrTArray<void*> fBlocks;
139     size_t          fBlockSize;
140     char            fBlockInitialStorage[NUM_INIT_BLOCK_PTRS*sizeof(void*)];
141     size_t          fItemSize;
142     int             fItemsPerBlock;
143     bool            fOwnFirstBlock;
144     int             fCount;
145 };
146 
147 template <typename T>
148 class GrTAllocator {
149 private:
150     GrAllocator fAllocator;
151 
152 public:
~GrTAllocator()153     virtual ~GrTAllocator() {};
154 
155     /**
156      * Create an allocator
157      *
158      * @param   itemsPerBlock   the number of items to allocate at once
159      * @param   initialBlock    optional memory to use for the first block.
160      *                          Must be at least size(T)*itemsPerBlock sized.
161      *                          Caller is responsible for freeing this memory.
162      */
GrTAllocator(int itemsPerBlock,void * initialBlock)163     GrTAllocator(int itemsPerBlock, void* initialBlock)
164         : fAllocator(sizeof(T), itemsPerBlock, initialBlock) {}
165 
166     /**
167      * Create an allocator using a GrAlignedTAlloc as the initial block.
168      *
169      * @param   initialBlock    specifies the storage for the initial block
170      *                          and the size of subsequent blocks.
171      */
172     template <int N>
GrTAllocator(GrAlignedSTStorage<N,T> * initialBlock)173     GrTAllocator(GrAlignedSTStorage<N,T>* initialBlock)
174         : fAllocator(sizeof(T), N, initialBlock->get()) {}
175 
176     /**
177      * Adds an item and returns it.
178      *
179      * @return the added item.
180      */
push_back()181     T& push_back() {
182         void* item = fAllocator.push_back();
183         GrAssert(NULL != item);
184         new (item) T;
185         return *(T*)item;
186     }
187 
188     /**
189      * removes all added items
190      */
reset()191     void reset() {
192         int c = fAllocator.count();
193         for (int i = 0; i < c; ++i) {
194             ((T*)fAllocator[i])->~T();
195         }
196         fAllocator.reset();
197     }
198 
199     /**
200      * count of items
201      */
count()202     int count() const {
203         return fAllocator.count();
204     }
205 
206     /**
207      * is the count 0
208      */
empty()209     bool empty() const { return fAllocator.empty(); }
210 
211     /**
212      * access last item, only call if count() != 0
213      */
back()214     T& back() {
215         return *(T*)fAllocator.back();
216     }
217 
218     /**
219      * access last item, only call if count() != 0
220      */
back()221     const T& back() const {
222         return *(const T*)fAllocator.back();
223     }
224 
225     /**
226      * access item by index.
227      */
228     T& operator[] (int i) {
229         return *(T*)(fAllocator[i]);
230     }
231 
232     /**
233      * access item by index.
234      */
235     const T& operator[] (int i) const {
236         return *(const T*)(fAllocator[i]);
237     }
238 };
239 
240 #endif
241