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