16819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton/* 26819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * Copyright 2014 Google Inc. 36819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * 46819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * Use of this source code is governed by a BSD-style license that can be 56819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * found in the LICENSE file. 66819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton */ 76819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 86819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton#ifndef GrTRecorder_DEFINED 96819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton#define GrTRecorder_DEFINED 106819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 116819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton#include "SkTemplates.h" 126819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton#include "SkTypes.h" 136819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 146819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltontemplate<typename TBase, typename TAlign> class GrTRecorder; 156819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltontemplate<typename TItem> struct GrTRecorderAllocWrapper; 166819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 176819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton/** 186819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * Records a list of items with a common base type, optional associated data, and 196819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * permanent memory addresses. 206819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * 216819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * This class preallocates its own chunks of memory for hosting objects, so new items can 226819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * be created without excessive calls to malloc(). 236819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * 246819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * To create a new item and append it to the back of the list, use the following macros: 256819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * 266819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * GrNEW_APPEND_TO_RECORDER(recorder, SubclassName, (args)) 276819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, SubclassName, (args), sizeOfData) 286819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * 296819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * Upon reset or delete, the items are destructed in the same order they were received, 306819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * not reverse (stack) order. 316819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * 326819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * @param TBase Common base type of items in the list. If TBase is not a class with a 336819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * virtual destructor, the client is responsible for invoking any necessary 346819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * destructors. 356819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * 366819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * For now, any subclass used in the list must have the same start address 376819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * as TBase (or in other words, the types must be convertible via 386819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * reinterpret_cast<>). Classes with multiple inheritance (or any subclass 396819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * on an obscure compiler) may not be compatible. This is runtime asserted 406819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * in debug builds. 416819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * 426819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * @param TAlign A type whose size is the desired memory alignment for object allocations. 436819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * This should be the largest known alignment requirement for all objects 446819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * that may be stored in the list. 456819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton */ 466819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltontemplate<typename TBase, typename TAlign> class GrTRecorder : SkNoncopyable { 476819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltonpublic: 486819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton class Iter; 4972badbd99e2321bfbcb22f78218bbafa71af4698cdalton class ReverseIter; 506819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 516819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton /** 526819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * Create a recorder. 536819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * 546819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * @param initialSizeInBytes The amount of memory reserved by the recorder initially, 556819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton and after calls to reset(). 566819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton */ 576819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton GrTRecorder(int initialSizeInBytes) 5877d77f446d1685cd21465627a747341c3c3665e4bsalomon : fHeadBlock(MemBlock::Alloc(LengthOf(initialSizeInBytes), NULL)), 596819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton fTailBlock(fHeadBlock), 606819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton fLastItem(NULL) {} 616819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 626819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton ~GrTRecorder() { 636819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton this->reset(); 646819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton MemBlock::Free(fHeadBlock); 656819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton } 666819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 676819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton bool empty() { return !fLastItem; } 686819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 696819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton TBase& back() { 706819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton SkASSERT(!this->empty()); 716819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton return *fLastItem; 726819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton } 736819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 746819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton /** 7577d77f446d1685cd21465627a747341c3c3665e4bsalomon * Removes and destroys the last block added to the recorder. It may not be called when the 7677d77f446d1685cd21465627a747341c3c3665e4bsalomon * recorder is empty. 7777d77f446d1685cd21465627a747341c3c3665e4bsalomon */ 7877d77f446d1685cd21465627a747341c3c3665e4bsalomon void pop_back(); 7977d77f446d1685cd21465627a747341c3c3665e4bsalomon 8077d77f446d1685cd21465627a747341c3c3665e4bsalomon /** 816819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * Destruct all items in the list and reset to empty. 826819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton */ 836819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton void reset(); 846819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 856819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton /** 866819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * Retrieve the extra data associated with an item that was allocated using 876819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * GrNEW_APPEND_WITH_DATA_TO_RECORDER(). 886819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * 896819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * @param item The item whose data to retrieve. The pointer must be of the same type 906819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * that was allocated initally; it can't be a pointer to a base class. 916819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * 926819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton * @return The item's associated data. 936819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton */ 946819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton template<typename TItem> static const void* GetDataForItem(const TItem* item) { 956819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton const TAlign* ptr = reinterpret_cast<const TAlign*>(item); 966819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton return &ptr[length_of<TItem>::kValue]; 976819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton } 986819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton template<typename TItem> static void* GetDataForItem(TItem* item) { 996819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton TAlign* ptr = reinterpret_cast<TAlign*>(item); 1006819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton return &ptr[length_of<TItem>::kValue]; 1016819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton } 1026819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 1036819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltonprivate: 1046819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton template<typename TItem> struct length_of { 1056819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton enum { kValue = (sizeof(TItem) + sizeof(TAlign) - 1) / sizeof(TAlign) }; 1066819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton }; 1076819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton static int LengthOf(int bytes) { return (bytes + sizeof(TAlign) - 1) / sizeof(TAlign); } 1086819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 1096819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton struct Header { 11077d77f446d1685cd21465627a747341c3c3665e4bsalomon int fTotalLength; // The length of an entry including header, item, and data in TAligns. 11177d77f446d1685cd21465627a747341c3c3665e4bsalomon int fPrevLength; // Same but for the previous entry. Used for iterating backwards. 1126819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton }; 1136819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton template<typename TItem> TItem* alloc_back(int dataLength); 1146819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 1156819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton struct MemBlock : SkNoncopyable { 11677d77f446d1685cd21465627a747341c3c3665e4bsalomon /** Allocates a new block and appends it to prev if not NULL. The length param is in units 11777d77f446d1685cd21465627a747341c3c3665e4bsalomon of TAlign. */ 11877d77f446d1685cd21465627a747341c3c3665e4bsalomon static MemBlock* Alloc(int length, MemBlock* prev) { 1196819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton MemBlock* block = reinterpret_cast<MemBlock*>( 1206819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton sk_malloc_throw(sizeof(TAlign) * (length_of<MemBlock>::kValue + length))); 1216819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton block->fLength = length; 1226819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton block->fBack = 0; 1236819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton block->fNext = NULL; 12477d77f446d1685cd21465627a747341c3c3665e4bsalomon block->fPrev = prev; 12577d77f446d1685cd21465627a747341c3c3665e4bsalomon if (prev) { 12677d77f446d1685cd21465627a747341c3c3665e4bsalomon SkASSERT(NULL == prev->fNext); 12777d77f446d1685cd21465627a747341c3c3665e4bsalomon prev->fNext = block; 12877d77f446d1685cd21465627a747341c3c3665e4bsalomon } 1296819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton return block; 1306819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton } 1316819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 13277d77f446d1685cd21465627a747341c3c3665e4bsalomon // Frees from this block forward. Also adjusts prev block's next ptr. 1336819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton static void Free(MemBlock* block) { 13477d77f446d1685cd21465627a747341c3c3665e4bsalomon if (block && block->fPrev) { 13577d77f446d1685cd21465627a747341c3c3665e4bsalomon SkASSERT(block->fPrev->fNext == block); 13677d77f446d1685cd21465627a747341c3c3665e4bsalomon block->fPrev->fNext = NULL; 13777d77f446d1685cd21465627a747341c3c3665e4bsalomon } 13877d77f446d1685cd21465627a747341c3c3665e4bsalomon while (block) { 13977d77f446d1685cd21465627a747341c3c3665e4bsalomon MemBlock* next = block->fNext; 14077d77f446d1685cd21465627a747341c3c3665e4bsalomon sk_free(block); 14177d77f446d1685cd21465627a747341c3c3665e4bsalomon block = next; 1426819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton } 1436819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton } 1446819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 1456819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton TAlign& operator [](int i) { 1466819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton return reinterpret_cast<TAlign*>(this)[length_of<MemBlock>::kValue + i]; 1476819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton } 1486819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 14977d77f446d1685cd21465627a747341c3c3665e4bsalomon int fLength; // Length in units of TAlign of the block. 15077d77f446d1685cd21465627a747341c3c3665e4bsalomon int fBack; // Offset, in TAligns, to unused portion of the memory block. 1516819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton MemBlock* fNext; 15277d77f446d1685cd21465627a747341c3c3665e4bsalomon MemBlock* fPrev; 1536819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton }; 1546819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton MemBlock* const fHeadBlock; 1556819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton MemBlock* fTailBlock; 1566819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 1576819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton TBase* fLastItem; 1586819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 1596819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton template<typename TItem> friend struct GrTRecorderAllocWrapper; 1606819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 1616819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton template <typename UBase, typename UAlign, typename UItem> 1626819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton friend void* operator new(size_t, GrTRecorder<UBase, UAlign>&, 1636819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton const GrTRecorderAllocWrapper<UItem>&); 1646819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 1656819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton friend class Iter; 16672badbd99e2321bfbcb22f78218bbafa71af4698cdalton friend class ReverseIter; 1676819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton}; 1686819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 1696819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton//////////////////////////////////////////////////////////////////////////////// 1706819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 1716819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltontemplate<typename TBase, typename TAlign> 17277d77f446d1685cd21465627a747341c3c3665e4bsalomonvoid GrTRecorder<TBase, TAlign>::pop_back() { 17377d77f446d1685cd21465627a747341c3c3665e4bsalomon SkASSERT(fLastItem); 17477d77f446d1685cd21465627a747341c3c3665e4bsalomon Header* header = reinterpret_cast<Header*>( 17577d77f446d1685cd21465627a747341c3c3665e4bsalomon reinterpret_cast<TAlign*>(fLastItem) - length_of<Header>::kValue); 17677d77f446d1685cd21465627a747341c3c3665e4bsalomon fTailBlock->fBack -= header->fTotalLength; 17777d77f446d1685cd21465627a747341c3c3665e4bsalomon fLastItem->~TBase(); 17877d77f446d1685cd21465627a747341c3c3665e4bsalomon 17977d77f446d1685cd21465627a747341c3c3665e4bsalomon int lastItemLength = header->fPrevLength; 18077d77f446d1685cd21465627a747341c3c3665e4bsalomon 18177d77f446d1685cd21465627a747341c3c3665e4bsalomon if (!header->fPrevLength) { 18277d77f446d1685cd21465627a747341c3c3665e4bsalomon // We popped the first entry in the recorder. 18377d77f446d1685cd21465627a747341c3c3665e4bsalomon SkASSERT(0 == fTailBlock->fBack); 18477d77f446d1685cd21465627a747341c3c3665e4bsalomon fLastItem = NULL; 18577d77f446d1685cd21465627a747341c3c3665e4bsalomon return; 18677d77f446d1685cd21465627a747341c3c3665e4bsalomon } 18772badbd99e2321bfbcb22f78218bbafa71af4698cdalton while (!fTailBlock->fBack) { 18877d77f446d1685cd21465627a747341c3c3665e4bsalomon // We popped the last entry in a block that isn't the head block. Move back a block but 18977d77f446d1685cd21465627a747341c3c3665e4bsalomon // don't free it since we'll probably grow into it shortly. 19077d77f446d1685cd21465627a747341c3c3665e4bsalomon fTailBlock = fTailBlock->fPrev; 19177d77f446d1685cd21465627a747341c3c3665e4bsalomon SkASSERT(fTailBlock); 19277d77f446d1685cd21465627a747341c3c3665e4bsalomon } 19377d77f446d1685cd21465627a747341c3c3665e4bsalomon fLastItem = reinterpret_cast<TBase*>( 19477d77f446d1685cd21465627a747341c3c3665e4bsalomon &(*fTailBlock)[fTailBlock->fBack - lastItemLength + length_of<Header>::kValue]); 19577d77f446d1685cd21465627a747341c3c3665e4bsalomon} 19677d77f446d1685cd21465627a747341c3c3665e4bsalomon 19777d77f446d1685cd21465627a747341c3c3665e4bsalomontemplate<typename TBase, typename TAlign> 1986819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltontemplate<typename TItem> 1996819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltonTItem* GrTRecorder<TBase, TAlign>::alloc_back(int dataLength) { 20077d77f446d1685cd21465627a747341c3c3665e4bsalomon // Find the header of the previous entry and get its length. We need to store that in the new 20177d77f446d1685cd21465627a747341c3c3665e4bsalomon // header for backwards iteration (pop_back()). 20277d77f446d1685cd21465627a747341c3c3665e4bsalomon int prevLength = 0; 20377d77f446d1685cd21465627a747341c3c3665e4bsalomon if (fLastItem) { 20477d77f446d1685cd21465627a747341c3c3665e4bsalomon Header* lastHeader = reinterpret_cast<Header*>( 20577d77f446d1685cd21465627a747341c3c3665e4bsalomon reinterpret_cast<TAlign*>(fLastItem) - length_of<Header>::kValue); 20677d77f446d1685cd21465627a747341c3c3665e4bsalomon prevLength = lastHeader->fTotalLength; 20777d77f446d1685cd21465627a747341c3c3665e4bsalomon } 20877d77f446d1685cd21465627a747341c3c3665e4bsalomon 2096819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton const int totalLength = length_of<Header>::kValue + length_of<TItem>::kValue + dataLength; 2106819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 21177d77f446d1685cd21465627a747341c3c3665e4bsalomon // Check if there is room in the current block and if not walk to next (allocating if 21277d77f446d1685cd21465627a747341c3c3665e4bsalomon // necessary). Note that pop_back() and reset() can leave the recorder in a state where it 21377d77f446d1685cd21465627a747341c3c3665e4bsalomon // has preallocated blocks hanging off the tail that are currently unused. 214c4650ee786f1420f548bcc33b207b83244474351cdalton while (fTailBlock->fBack + totalLength > fTailBlock->fLength) { 215c4650ee786f1420f548bcc33b207b83244474351cdalton if (!fTailBlock->fNext) { 21677d77f446d1685cd21465627a747341c3c3665e4bsalomon fTailBlock = MemBlock::Alloc(SkTMax(2 * fTailBlock->fLength, totalLength), fTailBlock); 21777d77f446d1685cd21465627a747341c3c3665e4bsalomon } else { 21877d77f446d1685cd21465627a747341c3c3665e4bsalomon fTailBlock = fTailBlock->fNext; 219c4650ee786f1420f548bcc33b207b83244474351cdalton } 220c4650ee786f1420f548bcc33b207b83244474351cdalton SkASSERT(0 == fTailBlock->fBack); 2216819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton } 2226819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 2236819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton Header* header = reinterpret_cast<Header*>(&(*fTailBlock)[fTailBlock->fBack]); 2246819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton TItem* rawPtr = reinterpret_cast<TItem*>( 2256819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton &(*fTailBlock)[fTailBlock->fBack + length_of<Header>::kValue]); 2266819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 2276819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton header->fTotalLength = totalLength; 22877d77f446d1685cd21465627a747341c3c3665e4bsalomon header->fPrevLength = prevLength; 2296819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton fLastItem = rawPtr; 2306819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton fTailBlock->fBack += totalLength; 2316819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 2326819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton // FIXME: We currently require that the base and subclass share the same start address. 2336819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton // This is not required by the C++ spec, and is likely to not be true in the case of 2346819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton // multiple inheritance or a base class that doesn't have virtual methods (when the 2356819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton // subclass does). It would be ideal to find a more robust solution that comes at no 2366819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton // extra cost to performance or code generality. 2376819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton SkDEBUGCODE(void* baseAddr = fLastItem; 2386819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton void* subclassAddr = rawPtr); 2396819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton SkASSERT(baseAddr == subclassAddr); 2406819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 2416819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton return rawPtr; 2426819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton} 2436819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 24472badbd99e2321bfbcb22f78218bbafa71af4698cdalton/** 24572badbd99e2321bfbcb22f78218bbafa71af4698cdalton * Iterates through a recorder from front to back. The initial state of the iterator is 24672badbd99e2321bfbcb22f78218bbafa71af4698cdalton * to not have the front item loaded yet; next() must be called first. Usage model: 24772badbd99e2321bfbcb22f78218bbafa71af4698cdalton * 24872badbd99e2321bfbcb22f78218bbafa71af4698cdalton * GrTRecorder<TBase, TAlign>::Iter iter(recorder); 24972badbd99e2321bfbcb22f78218bbafa71af4698cdalton * while (iter.next()) { 25072badbd99e2321bfbcb22f78218bbafa71af4698cdalton * iter->doSomething(); 25172badbd99e2321bfbcb22f78218bbafa71af4698cdalton * } 25272badbd99e2321bfbcb22f78218bbafa71af4698cdalton */ 2536819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltontemplate<typename TBase, typename TAlign> 2546819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltonclass GrTRecorder<TBase, TAlign>::Iter { 2556819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltonpublic: 2566819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton Iter(GrTRecorder& recorder) : fBlock(recorder.fHeadBlock), fPosition(0), fItem(NULL) {} 2576819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 2586819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton bool next() { 259c4650ee786f1420f548bcc33b207b83244474351cdalton while (fPosition >= fBlock->fBack) { 2606819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton SkASSERT(fPosition == fBlock->fBack); 2616819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton if (!fBlock->fNext) { 2626819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton return false; 2636819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton } 2646819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton fBlock = fBlock->fNext; 2656819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton fPosition = 0; 2666819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton } 2676819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 2686819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton Header* header = reinterpret_cast<Header*>(&(*fBlock)[fPosition]); 2696819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton fItem = reinterpret_cast<TBase*>(&(*fBlock)[fPosition + length_of<Header>::kValue]); 2706819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton fPosition += header->fTotalLength; 2716819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton return true; 2726819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton } 2736819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 2746819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton TBase* get() const { 2756819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton SkASSERT(fItem); 2766819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton return fItem; 2776819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton } 2786819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 2796819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton TBase* operator->() const { return this->get(); } 2806819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 2816819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltonprivate: 2826819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton MemBlock* fBlock; 2836819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton int fPosition; 2846819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton TBase* fItem; 2856819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton}; 2866819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 28772badbd99e2321bfbcb22f78218bbafa71af4698cdalton/** 28872badbd99e2321bfbcb22f78218bbafa71af4698cdalton * Iterates through a recorder in reverse, from back to front. This version mirrors "Iter", 28972badbd99e2321bfbcb22f78218bbafa71af4698cdalton * so the initial state is to have recorder.back() loaded already. (Note that this will 29072badbd99e2321bfbcb22f78218bbafa71af4698cdalton * assert if the recorder is empty.) Usage model: 29172badbd99e2321bfbcb22f78218bbafa71af4698cdalton * 29272badbd99e2321bfbcb22f78218bbafa71af4698cdalton * GrTRecorder<TBase, TAlign>::ReverseIter reverseIter(recorder); 29372badbd99e2321bfbcb22f78218bbafa71af4698cdalton * do { 29472badbd99e2321bfbcb22f78218bbafa71af4698cdalton * reverseIter->doSomething(); 29572badbd99e2321bfbcb22f78218bbafa71af4698cdalton * } while (reverseIter.previous()); 29672badbd99e2321bfbcb22f78218bbafa71af4698cdalton */ 29772badbd99e2321bfbcb22f78218bbafa71af4698cdaltontemplate<typename TBase, typename TAlign> 29872badbd99e2321bfbcb22f78218bbafa71af4698cdaltonclass GrTRecorder<TBase, TAlign>::ReverseIter { 29972badbd99e2321bfbcb22f78218bbafa71af4698cdaltonpublic: 30072badbd99e2321bfbcb22f78218bbafa71af4698cdalton ReverseIter(GrTRecorder& recorder) 30172badbd99e2321bfbcb22f78218bbafa71af4698cdalton : fBlock(recorder.fTailBlock), 30272badbd99e2321bfbcb22f78218bbafa71af4698cdalton fItem(&recorder.back()) { 30372badbd99e2321bfbcb22f78218bbafa71af4698cdalton Header* lastHeader = reinterpret_cast<Header*>( 30472badbd99e2321bfbcb22f78218bbafa71af4698cdalton reinterpret_cast<TAlign*>(fItem) - length_of<Header>::kValue); 30572badbd99e2321bfbcb22f78218bbafa71af4698cdalton fPosition = fBlock->fBack - lastHeader->fTotalLength; 30672badbd99e2321bfbcb22f78218bbafa71af4698cdalton } 30772badbd99e2321bfbcb22f78218bbafa71af4698cdalton 30872badbd99e2321bfbcb22f78218bbafa71af4698cdalton bool previous() { 30972badbd99e2321bfbcb22f78218bbafa71af4698cdalton Header* header = reinterpret_cast<Header*>(&(*fBlock)[fPosition]); 31072badbd99e2321bfbcb22f78218bbafa71af4698cdalton 31172badbd99e2321bfbcb22f78218bbafa71af4698cdalton while (0 == fPosition) { 31272badbd99e2321bfbcb22f78218bbafa71af4698cdalton if (!fBlock->fPrev) { 31372badbd99e2321bfbcb22f78218bbafa71af4698cdalton // We've reached the front of the recorder. 31472badbd99e2321bfbcb22f78218bbafa71af4698cdalton return false; 31572badbd99e2321bfbcb22f78218bbafa71af4698cdalton } 31672badbd99e2321bfbcb22f78218bbafa71af4698cdalton fBlock = fBlock->fPrev; 31772badbd99e2321bfbcb22f78218bbafa71af4698cdalton fPosition = fBlock->fBack; 31872badbd99e2321bfbcb22f78218bbafa71af4698cdalton } 31972badbd99e2321bfbcb22f78218bbafa71af4698cdalton 32072badbd99e2321bfbcb22f78218bbafa71af4698cdalton fPosition -= header->fPrevLength; 32172badbd99e2321bfbcb22f78218bbafa71af4698cdalton SkASSERT(fPosition >= 0); 32272badbd99e2321bfbcb22f78218bbafa71af4698cdalton 32372badbd99e2321bfbcb22f78218bbafa71af4698cdalton fItem = reinterpret_cast<TBase*>(&(*fBlock)[fPosition + length_of<Header>::kValue]); 32472badbd99e2321bfbcb22f78218bbafa71af4698cdalton return true; 32572badbd99e2321bfbcb22f78218bbafa71af4698cdalton } 32672badbd99e2321bfbcb22f78218bbafa71af4698cdalton 32772badbd99e2321bfbcb22f78218bbafa71af4698cdalton TBase* get() const { return fItem; } 32872badbd99e2321bfbcb22f78218bbafa71af4698cdalton TBase* operator->() const { return this->get(); } 32972badbd99e2321bfbcb22f78218bbafa71af4698cdalton 33072badbd99e2321bfbcb22f78218bbafa71af4698cdaltonprivate: 33172badbd99e2321bfbcb22f78218bbafa71af4698cdalton MemBlock* fBlock; 33272badbd99e2321bfbcb22f78218bbafa71af4698cdalton int fPosition; 33372badbd99e2321bfbcb22f78218bbafa71af4698cdalton TBase* fItem; 33472badbd99e2321bfbcb22f78218bbafa71af4698cdalton}; 33572badbd99e2321bfbcb22f78218bbafa71af4698cdalton 3366819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltontemplate<typename TBase, typename TAlign> 3376819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltonvoid GrTRecorder<TBase, TAlign>::reset() { 3386819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton Iter iter(*this); 3396819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton while (iter.next()) { 3406819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton iter->~TBase(); 3416819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton } 342c4650ee786f1420f548bcc33b207b83244474351cdalton 343c4650ee786f1420f548bcc33b207b83244474351cdalton // Assume the next time this recorder fills up it will use approximately the same 344c4650ee786f1420f548bcc33b207b83244474351cdalton // amount of space as last time. Leave enough space for up to ~50% growth; free 345c4650ee786f1420f548bcc33b207b83244474351cdalton // everything else. 346c4650ee786f1420f548bcc33b207b83244474351cdalton if (fTailBlock->fBack <= fTailBlock->fLength / 2) { 347c4650ee786f1420f548bcc33b207b83244474351cdalton MemBlock::Free(fTailBlock->fNext); 348c4650ee786f1420f548bcc33b207b83244474351cdalton } else if (fTailBlock->fNext) { 349c4650ee786f1420f548bcc33b207b83244474351cdalton MemBlock::Free(fTailBlock->fNext->fNext); 350c4650ee786f1420f548bcc33b207b83244474351cdalton fTailBlock->fNext->fNext = NULL; 351c4650ee786f1420f548bcc33b207b83244474351cdalton } 352c4650ee786f1420f548bcc33b207b83244474351cdalton 353c4650ee786f1420f548bcc33b207b83244474351cdalton for (MemBlock* block = fHeadBlock; block; block = block->fNext) { 354c4650ee786f1420f548bcc33b207b83244474351cdalton block->fBack = 0; 355c4650ee786f1420f548bcc33b207b83244474351cdalton } 356c4650ee786f1420f548bcc33b207b83244474351cdalton 3576819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton fTailBlock = fHeadBlock; 3586819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton fLastItem = NULL; 3596819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton} 3606819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 3616819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton//////////////////////////////////////////////////////////////////////////////// 3626819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 3636819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltontemplate<typename TItem> struct GrTRecorderAllocWrapper { 3646819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton GrTRecorderAllocWrapper() : fDataLength(0) {} 3656819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 3666819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton template <typename TBase, typename TAlign> 3676819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton GrTRecorderAllocWrapper(const GrTRecorder<TBase, TAlign>&, int sizeOfData) 3686819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton : fDataLength(GrTRecorder<TBase, TAlign>::LengthOf(sizeOfData)) {} 3696819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 3706819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton const int fDataLength; 3716819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton}; 3726819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 3736819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltontemplate <typename TBase, typename TAlign, typename TItem> 3746819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltonvoid* operator new(size_t size, GrTRecorder<TBase, TAlign>& recorder, 3756819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton const GrTRecorderAllocWrapper<TItem>& wrapper) { 3766819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton SkASSERT(size == sizeof(TItem)); 3776819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton return recorder.template alloc_back<TItem>(wrapper.fDataLength); 3786819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton} 3796819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 3806819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltontemplate <typename TBase, typename TAlign, typename TItem> 3816819df36446f6fdcbd17d83a72a03de46e6d0d2dcdaltonvoid operator delete(void*, GrTRecorder<TBase, TAlign>&, const GrTRecorderAllocWrapper<TItem>&) { 3826819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton // We only provide an operator delete to work around compiler warnings that can come 3836819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton // up for an unmatched operator new when compiling with exceptions. 3846819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton SK_CRASH(); 3856819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton} 3866819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 3876819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton#define GrNEW_APPEND_TO_RECORDER(recorder, type_name, args) \ 3886819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton (new (recorder, GrTRecorderAllocWrapper<type_name>()) type_name args) 3896819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 3906819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton#define GrNEW_APPEND_WITH_DATA_TO_RECORDER(recorder, type_name, args, size_of_data) \ 3916819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton (new (recorder, GrTRecorderAllocWrapper<type_name>(recorder, size_of_data)) type_name args) 3926819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton 3936819df36446f6fdcbd17d83a72a03de46e6d0d2dcdalton#endif 394