| 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 |