OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef GrTRecorder_DEFINED | 8 #ifndef GrTRecorder_DEFINED |
9 #define GrTRecorder_DEFINED | 9 #define GrTRecorder_DEFINED |
10 | 10 |
(...skipping 28 matching lines...) Expand all Loading... |
39 * on an obscure compiler) may not be compatible. This is runtime
asserted | 39 * on an obscure compiler) may not be compatible. This is runtime
asserted |
40 * in debug builds. | 40 * in debug builds. |
41 * | 41 * |
42 * @param TAlign A type whose size is the desired memory alignment for object a
llocations. | 42 * @param TAlign A type whose size is the desired memory alignment for object a
llocations. |
43 * This should be the largest known alignment requirement for all
objects | 43 * This should be the largest known alignment requirement for all
objects |
44 * that may be stored in the list. | 44 * that may be stored in the list. |
45 */ | 45 */ |
46 template<typename TBase, typename TAlign> class GrTRecorder : SkNoncopyable { | 46 template<typename TBase, typename TAlign> class GrTRecorder : SkNoncopyable { |
47 public: | 47 public: |
48 class Iter; | 48 class Iter; |
| 49 class ReverseIter; |
49 | 50 |
50 /** | 51 /** |
51 * Create a recorder. | 52 * Create a recorder. |
52 * | 53 * |
53 * @param initialSizeInBytes The amount of memory reserved by the recorder
initially, | 54 * @param initialSizeInBytes The amount of memory reserved by the recorder
initially, |
54 and after calls to reset(). | 55 and after calls to reset(). |
55 */ | 56 */ |
56 GrTRecorder(int initialSizeInBytes) | 57 GrTRecorder(int initialSizeInBytes) |
57 : fHeadBlock(MemBlock::Alloc(LengthOf(initialSizeInBytes), NULL)), | 58 : fHeadBlock(MemBlock::Alloc(LengthOf(initialSizeInBytes), NULL)), |
58 fTailBlock(fHeadBlock), | 59 fTailBlock(fHeadBlock), |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
155 | 156 |
156 TBase* fLastItem; | 157 TBase* fLastItem; |
157 | 158 |
158 template<typename TItem> friend struct GrTRecorderAllocWrapper; | 159 template<typename TItem> friend struct GrTRecorderAllocWrapper; |
159 | 160 |
160 template <typename UBase, typename UAlign, typename UItem> | 161 template <typename UBase, typename UAlign, typename UItem> |
161 friend void* operator new(size_t, GrTRecorder<UBase, UAlign>&, | 162 friend void* operator new(size_t, GrTRecorder<UBase, UAlign>&, |
162 const GrTRecorderAllocWrapper<UItem>&); | 163 const GrTRecorderAllocWrapper<UItem>&); |
163 | 164 |
164 friend class Iter; | 165 friend class Iter; |
| 166 friend class ReverseIter; |
165 }; | 167 }; |
166 | 168 |
167 //////////////////////////////////////////////////////////////////////////////// | 169 //////////////////////////////////////////////////////////////////////////////// |
168 | 170 |
169 template<typename TBase, typename TAlign> | 171 template<typename TBase, typename TAlign> |
170 void GrTRecorder<TBase, TAlign>::pop_back() { | 172 void GrTRecorder<TBase, TAlign>::pop_back() { |
171 SkASSERT(fLastItem); | 173 SkASSERT(fLastItem); |
172 Header* header = reinterpret_cast<Header*>( | 174 Header* header = reinterpret_cast<Header*>( |
173 reinterpret_cast<TAlign*>(fLastItem) - length_of<Header>::kValue); | 175 reinterpret_cast<TAlign*>(fLastItem) - length_of<Header>::kValue); |
174 fTailBlock->fBack -= header->fTotalLength; | 176 fTailBlock->fBack -= header->fTotalLength; |
175 fLastItem->~TBase(); | 177 fLastItem->~TBase(); |
176 | 178 |
177 int lastItemLength = header->fPrevLength; | 179 int lastItemLength = header->fPrevLength; |
178 | 180 |
179 if (!header->fPrevLength) { | 181 if (!header->fPrevLength) { |
180 // We popped the first entry in the recorder. | 182 // We popped the first entry in the recorder. |
181 SkASSERT(0 == fTailBlock->fBack); | 183 SkASSERT(0 == fTailBlock->fBack); |
182 fLastItem = NULL; | 184 fLastItem = NULL; |
183 return; | 185 return; |
184 } | 186 } |
185 if (!fTailBlock->fBack) { | 187 while (!fTailBlock->fBack) { |
186 // We popped the last entry in a block that isn't the head block. Move b
ack a block but | 188 // We popped the last entry in a block that isn't the head block. Move b
ack a block but |
187 // don't free it since we'll probably grow into it shortly. | 189 // don't free it since we'll probably grow into it shortly. |
188 fTailBlock = fTailBlock->fPrev; | 190 fTailBlock = fTailBlock->fPrev; |
189 SkASSERT(fTailBlock); | 191 SkASSERT(fTailBlock); |
190 } | 192 } |
191 fLastItem = reinterpret_cast<TBase*>( | 193 fLastItem = reinterpret_cast<TBase*>( |
192 &(*fTailBlock)[fTailBlock->fBack - lastItemLength + length_of<Header>::k
Value]); | 194 &(*fTailBlock)[fTailBlock->fBack - lastItemLength + length_of<Header>::k
Value]); |
193 } | 195 } |
194 | 196 |
195 template<typename TBase, typename TAlign> | 197 template<typename TBase, typename TAlign> |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
232 // multiple inheritance or a base class that doesn't have virtual methods (w
hen the | 234 // multiple inheritance or a base class that doesn't have virtual methods (w
hen the |
233 // subclass does). It would be ideal to find a more robust solution that com
es at no | 235 // subclass does). It would be ideal to find a more robust solution that com
es at no |
234 // extra cost to performance or code generality. | 236 // extra cost to performance or code generality. |
235 SkDEBUGCODE(void* baseAddr = fLastItem; | 237 SkDEBUGCODE(void* baseAddr = fLastItem; |
236 void* subclassAddr = rawPtr); | 238 void* subclassAddr = rawPtr); |
237 SkASSERT(baseAddr == subclassAddr); | 239 SkASSERT(baseAddr == subclassAddr); |
238 | 240 |
239 return rawPtr; | 241 return rawPtr; |
240 } | 242 } |
241 | 243 |
| 244 /** |
| 245 * Iterates through a recorder from front to back. The initial state of the iter
ator is |
| 246 * to not have the front item loaded yet; next() must be called first. Usage mod
el: |
| 247 * |
| 248 * GrTRecorder<TBase, TAlign>::Iter iter(recorder); |
| 249 * while (iter.next()) { |
| 250 * iter->doSomething(); |
| 251 * } |
| 252 */ |
242 template<typename TBase, typename TAlign> | 253 template<typename TBase, typename TAlign> |
243 class GrTRecorder<TBase, TAlign>::Iter { | 254 class GrTRecorder<TBase, TAlign>::Iter { |
244 public: | 255 public: |
245 Iter(GrTRecorder& recorder) : fBlock(recorder.fHeadBlock), fPosition(0), fIt
em(NULL) {} | 256 Iter(GrTRecorder& recorder) : fBlock(recorder.fHeadBlock), fPosition(0), fIt
em(NULL) {} |
246 | 257 |
247 bool next() { | 258 bool next() { |
248 while (fPosition >= fBlock->fBack) { | 259 while (fPosition >= fBlock->fBack) { |
249 SkASSERT(fPosition == fBlock->fBack); | 260 SkASSERT(fPosition == fBlock->fBack); |
250 if (!fBlock->fNext) { | 261 if (!fBlock->fNext) { |
251 return false; | 262 return false; |
(...skipping 14 matching lines...) Expand all Loading... |
266 } | 277 } |
267 | 278 |
268 TBase* operator->() const { return this->get(); } | 279 TBase* operator->() const { return this->get(); } |
269 | 280 |
270 private: | 281 private: |
271 MemBlock* fBlock; | 282 MemBlock* fBlock; |
272 int fPosition; | 283 int fPosition; |
273 TBase* fItem; | 284 TBase* fItem; |
274 }; | 285 }; |
275 | 286 |
| 287 /** |
| 288 * Iterates through a recorder in reverse, from back to front. This version mirr
ors "Iter", |
| 289 * so the initial state is to have recorder.back() loaded already. (Note that th
is will |
| 290 * assert if the recorder is empty.) Usage model: |
| 291 * |
| 292 * GrTRecorder<TBase, TAlign>::ReverseIter reverseIter(recorder); |
| 293 * do { |
| 294 * reverseIter->doSomething(); |
| 295 * } while (reverseIter.previous()); |
| 296 */ |
| 297 template<typename TBase, typename TAlign> |
| 298 class GrTRecorder<TBase, TAlign>::ReverseIter { |
| 299 public: |
| 300 ReverseIter(GrTRecorder& recorder) |
| 301 : fBlock(recorder.fTailBlock), |
| 302 fItem(&recorder.back()) { |
| 303 Header* lastHeader = reinterpret_cast<Header*>( |
| 304 reinterpret_cast<TAlign*>(fItem) - length_of<Header>::kValue); |
| 305 fPosition = fBlock->fBack - lastHeader->fTotalLength; |
| 306 } |
| 307 |
| 308 bool previous() { |
| 309 Header* header = reinterpret_cast<Header*>(&(*fBlock)[fPosition]); |
| 310 |
| 311 while (0 == fPosition) { |
| 312 if (!fBlock->fPrev) { |
| 313 // We've reached the front of the recorder. |
| 314 return false; |
| 315 } |
| 316 fBlock = fBlock->fPrev; |
| 317 fPosition = fBlock->fBack; |
| 318 } |
| 319 |
| 320 fPosition -= header->fPrevLength; |
| 321 SkASSERT(fPosition >= 0); |
| 322 |
| 323 fItem = reinterpret_cast<TBase*>(&(*fBlock)[fPosition + length_of<Header
>::kValue]); |
| 324 return true; |
| 325 } |
| 326 |
| 327 TBase* get() const { return fItem; } |
| 328 TBase* operator->() const { return this->get(); } |
| 329 |
| 330 private: |
| 331 MemBlock* fBlock; |
| 332 int fPosition; |
| 333 TBase* fItem; |
| 334 }; |
| 335 |
276 template<typename TBase, typename TAlign> | 336 template<typename TBase, typename TAlign> |
277 void GrTRecorder<TBase, TAlign>::reset() { | 337 void GrTRecorder<TBase, TAlign>::reset() { |
278 Iter iter(*this); | 338 Iter iter(*this); |
279 while (iter.next()) { | 339 while (iter.next()) { |
280 iter->~TBase(); | 340 iter->~TBase(); |
281 } | 341 } |
282 | 342 |
283 // Assume the next time this recorder fills up it will use approximately the
same | 343 // Assume the next time this recorder fills up it will use approximately the
same |
284 // amount of space as last time. Leave enough space for up to ~50% growth; f
ree | 344 // amount of space as last time. Leave enough space for up to ~50% growth; f
ree |
285 // everything else. | 345 // everything else. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 SK_CRASH(); | 384 SK_CRASH(); |
325 } | 385 } |
326 | 386 |
327 #define GrNEW_APPEND_TO_RECORDER(recorder, type_name, args) \ | 387 #define GrNEW_APPEND_TO_RECORDER(recorder, type_name, args) \ |
328 (new (recorder, GrTRecorderAllocWrapper<type_name>()) type_name args) | 388 (new (recorder, GrTRecorderAllocWrapper<type_name>()) type_name args) |
329 | 389 |
330 #define GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, type_name, args, size_of_da
ta) \ | 390 #define GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, type_name, args, size_of_da
ta) \ |
331 (new (recorder, GrTRecorderAllocWrapper<type_name>(recorder, size_of_data))
type_name args) | 391 (new (recorder, GrTRecorderAllocWrapper<type_name>(recorder, size_of_data))
type_name args) |
332 | 392 |
333 #endif | 393 #endif |
OLD | NEW |