Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / GrAllocator.h
1 /*
2  * 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.
6  */
7
8 #ifndef GrAllocator_DEFINED
9 #define GrAllocator_DEFINED
10
11 #include "GrConfig.h"
12 #include "GrTypes.h"
13 #include "SkTArray.h"
14 #include "SkTypes.h"
15
16 class GrAllocator : SkNoncopyable {
17 public:
18     ~GrAllocator() {
19         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      */
31     GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock) :
32             fItemSize(itemSize),
33             fItemsPerBlock(itemsPerBlock),
34             fOwnFirstBlock(NULL == initialBlock),
35             fCount(0) {
36         SkASSERT(itemsPerBlock > 0);
37         fBlockSize = fItemSize * fItemsPerBlock;
38         fBlocks.push_back() = initialBlock;
39         SkDEBUGCODE(if (!fOwnFirstBlock) {*((char*)initialBlock+fBlockSize-1)='a';} );
40     }
41
42     /*
43      * Set first block of memory to write into.  Must be called before any other methods.
44      * This requires that you have passed NULL in the constructor.
45      *
46      * @param   initialBlock    optional memory to use for the first block.
47      *                          Must be at least itemSize*itemsPerBlock sized.
48      *                          Caller is responsible for freeing this memory.
49      */
50     void setInitialBlock(void* initialBlock) {
51         SkASSERT(0 == fCount);
52         SkASSERT(1 == fBlocks.count());
53         SkASSERT(NULL == fBlocks.back());
54         fOwnFirstBlock = false;
55         fBlocks.back() = initialBlock;
56     }
57
58     /**
59      * Adds an item and returns pointer to it.
60      *
61      * @return pointer to the added item.
62      */
63     void* push_back() {
64         int indexInBlock = fCount % fItemsPerBlock;
65         // we always have at least one block
66         if (0 == indexInBlock) {
67             if (0 != fCount) {
68                 fBlocks.push_back() = sk_malloc_throw(fBlockSize);
69             } else if (fOwnFirstBlock) {
70                 fBlocks[0] = sk_malloc_throw(fBlockSize);
71             }
72         }
73         void* ret = (char*)fBlocks[fCount/fItemsPerBlock] +
74                     fItemSize * indexInBlock;
75         ++fCount;
76         return ret;
77     }
78
79     /**
80      * removes all added items
81      */
82     void reset() {
83         int blockCount = SkTMax((unsigned)1,
84                                GrUIDivRoundUp(fCount, fItemsPerBlock));
85         for (int i = 1; i < blockCount; ++i) {
86             sk_free(fBlocks[i]);
87         }
88         if (fOwnFirstBlock) {
89             sk_free(fBlocks[0]);
90             fBlocks[0] = NULL;
91         }
92         fBlocks.pop_back_n(blockCount-1);
93         fCount = 0;
94     }
95
96     /**
97      * count of items
98      */
99     int count() const {
100         return fCount;
101     }
102
103     /**
104      * is the count 0
105      */
106     bool empty() const { return fCount == 0; }
107
108     /**
109      * access last item, only call if count() != 0
110      */
111     void* back() {
112         SkASSERT(fCount);
113         return (*this)[fCount-1];
114     }
115
116     /**
117      * access last item, only call if count() != 0
118      */
119     const void* back() const {
120         SkASSERT(fCount);
121         return (*this)[fCount-1];
122     }
123
124     /**
125      * access item by index.
126      */
127     void* operator[] (int i) {
128         SkASSERT(i >= 0 && i < fCount);
129         return (char*)fBlocks[i / fItemsPerBlock] +
130                fItemSize * (i % fItemsPerBlock);
131     }
132
133     /**
134      * access item by index.
135      */
136     const void* operator[] (int i) const {
137         SkASSERT(i >= 0 && i < fCount);
138         return (const char*)fBlocks[i / fItemsPerBlock] +
139                fItemSize * (i % fItemsPerBlock);
140     }
141
142 private:
143     static const int NUM_INIT_BLOCK_PTRS = 8;
144
145     SkSTArray<NUM_INIT_BLOCK_PTRS, void*>   fBlocks;
146     size_t                                  fBlockSize;
147     size_t                                  fItemSize;
148     int                                     fItemsPerBlock;
149     bool                                    fOwnFirstBlock;
150     int                                     fCount;
151
152     typedef SkNoncopyable INHERITED;
153 };
154
155 template <typename T>
156 class GrTAllocator : SkNoncopyable {
157 public:
158     virtual ~GrTAllocator() { this->reset(); };
159
160     /**
161      * Create an allocator
162      *
163      * @param   itemsPerBlock   the number of items to allocate at once
164      */
165     explicit GrTAllocator(int itemsPerBlock)
166         : fAllocator(sizeof(T), itemsPerBlock, NULL) {}
167
168     /**
169      * Adds an item and returns it.
170      *
171      * @return the added item.
172      */
173     T& push_back() {
174         void* item = fAllocator.push_back();
175         SkASSERT(NULL != item);
176         SkNEW_PLACEMENT(item, T);
177         return *(T*)item;
178     }
179
180     T& push_back(const T& t) {
181         void* item = fAllocator.push_back();
182         SkASSERT(NULL != item);
183         SkNEW_PLACEMENT_ARGS(item, T, (t));
184         return *(T*)item;
185     }
186
187     /**
188      * removes all added items
189      */
190     void reset() {
191         int c = fAllocator.count();
192         for (int i = 0; i < c; ++i) {
193             ((T*)fAllocator[i])->~T();
194         }
195         fAllocator.reset();
196     }
197
198     /**
199      * count of items
200      */
201     int count() const {
202         return fAllocator.count();
203     }
204
205     /**
206      * is the count 0
207      */
208     bool empty() const { return fAllocator.empty(); }
209
210     /**
211      * access last item, only call if count() != 0
212      */
213     T& back() {
214         return *(T*)fAllocator.back();
215     }
216
217     /**
218      * access last item, only call if count() != 0
219      */
220     const T& back() const {
221         return *(const T*)fAllocator.back();
222     }
223
224     /**
225      * access item by index.
226      */
227     T& operator[] (int i) {
228         return *(T*)(fAllocator[i]);
229     }
230
231     /**
232      * access item by index.
233      */
234     const T& operator[] (int i) const {
235         return *(const T*)(fAllocator[i]);
236     }
237
238 protected:
239     /*
240      * Set first block of memory to write into.  Must be called before any other methods.
241      *
242      * @param   initialBlock    optional memory to use for the first block.
243      *                          Must be at least size(T)*itemsPerBlock sized.
244      *                          Caller is responsible for freeing this memory.
245      */
246     void setInitialBlock(void* initialBlock) {
247         fAllocator.setInitialBlock(initialBlock);
248     }
249
250 private:
251     GrAllocator fAllocator;
252     typedef SkNoncopyable INHERITED;
253 };
254
255 template <int N, typename T> class GrSTAllocator : public GrTAllocator<T> {
256 private:
257     typedef GrTAllocator<T> INHERITED;
258
259 public:
260     GrSTAllocator() : INHERITED(N) {
261         this->setInitialBlock(fStorage.get());
262     }
263
264 private:
265     SkAlignedSTStorage<N, T> fStorage;
266 };
267
268 #endif