1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2010 Google Inc. 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifndef GrAllocator_DEFINED 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define GrAllocator_DEFINED 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrConfig.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "GrTypes.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTArray.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTypes.h" 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass GrAllocator : SkNoncopyable { 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ~GrAllocator() { this->reset(); } 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Create an allocator 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @param itemSize the size of each item to allocate 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @param itemsPerBlock the number of items to allocate at once 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @param initialBlock optional memory to use for the first block. 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Must be at least itemSize*itemsPerBlock sized. 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Caller is responsible for freeing this memory. 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock) 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fItemSize(itemSize) 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fItemsPerBlock(itemsPerBlock) 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fOwnFirstBlock(nullptr == initialBlock) 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fCount(0) 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fInsertionIndexInBlock(0) { 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(itemsPerBlock > 0); 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBlockSize = fItemSize * fItemsPerBlock; 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fOwnFirstBlock) { 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This force us to allocate a new block on push_back(). 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fInsertionIndexInBlock = fItemsPerBlock; 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBlocks.push_back() = initialBlock; 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fInsertionIndexInBlock = 0; 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Adds an item and returns pointer to it. 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @return pointer to the added item. 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void* push_back() { 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // we always have at least one block 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fItemsPerBlock == fInsertionIndexInBlock) { 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBlocks.push_back() = sk_malloc_throw(fBlockSize); 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fInsertionIndexInBlock = 0; 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void* ret = (char*)fBlocks.back() + fItemSize * fInsertionIndexInBlock; 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++fCount; 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++fInsertionIndexInBlock; 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return ret; 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Remove the last item, only call if count() != 0 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void pop_back() { 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fCount); 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fInsertionIndexInBlock > 0); 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot --fInsertionIndexInBlock; 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot --fCount; 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == fInsertionIndexInBlock) { 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Never delete the first block 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fBlocks.count() > 1) { 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_free(fBlocks.back()); 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBlocks.pop_back(); 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fInsertionIndexInBlock = fItemsPerBlock; 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Removes all added items. 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void reset() { 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int firstBlockToFree = fOwnFirstBlock ? 0 : 1; 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = firstBlockToFree; i < fBlocks.count(); ++i) { 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_free(fBlocks[i]); 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fOwnFirstBlock) { 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBlocks.reset(); 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // This force us to allocate a new block on push_back(). 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fInsertionIndexInBlock = fItemsPerBlock; 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBlocks.pop_back_n(fBlocks.count() - 1); 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fInsertionIndexInBlock = 0; 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fCount = 0; 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Returns the item count. 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count() const { 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fCount; 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Is the count 0? 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool empty() const { return 0 == fCount; } 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Access last item, only call if count() != 0 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void* back() { 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fCount); 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fInsertionIndexInBlock > 0); 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return (char*)(fBlocks.back()) + (fInsertionIndexInBlock - 1) * fItemSize; 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Access last item, only call if count() != 0 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const void* back() const { 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fCount); 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fInsertionIndexInBlock > 0); 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return (const char*)(fBlocks.back()) + (fInsertionIndexInBlock - 1) * fItemSize; 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Iterates through the allocator. This is faster than using operator[] when walking linearly 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * through the allocator. 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot class Iter { 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot public: 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Initializes the iterator. next() must be called before get(). 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Iter(const GrAllocator* allocator) 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fAllocator(allocator) 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fBlockIndex(-1) 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fIndexInBlock(allocator->fItemsPerBlock - 1) 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fItemIndex(-1) {} 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Advances the iterator. Iteration is finished when next() returns false. 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool next() { 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++fIndexInBlock; 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++fItemIndex; 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fIndexInBlock == fAllocator->fItemsPerBlock) { 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ++fBlockIndex; 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fIndexInBlock = 0; 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fItemIndex < fAllocator->fCount; 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Gets the current iterator value. Call next() at least once before calling. Don't call 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * after next() returns false. 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void* get() const { 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fItemIndex >= 0 && fItemIndex < fAllocator->fCount); 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return (char*) fAllocator->fBlocks[fBlockIndex] + fIndexInBlock * fAllocator->fItemSize; 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot private: 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const GrAllocator* fAllocator; 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fBlockIndex; 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fIndexInBlock; 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fItemIndex; 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Access item by index. 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void* operator[] (int i) { 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(i >= 0 && i < fCount); 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return (char*)fBlocks[i / fItemsPerBlock] + 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fItemSize * (i % fItemsPerBlock); 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Access item by index. 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const void* operator[] (int i) const { 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(i >= 0 && i < fCount); 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return (const char*)fBlocks[i / fItemsPerBlock] + 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fItemSize * (i % fItemsPerBlock); 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected: 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Set first block of memory to write into. Must be called before any other methods. 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * This requires that you have passed nullptr in the constructor. 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @param initialBlock optional memory to use for the first block. 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Must be at least itemSize*itemsPerBlock sized. 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Caller is responsible for freeing this memory. 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setInitialBlock(void* initialBlock) { 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(0 == fCount); 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(0 == fBlocks.count()); 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fItemsPerBlock == fInsertionIndexInBlock); 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fOwnFirstBlock = false; 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBlocks.push_back() = initialBlock; 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fInsertionIndexInBlock = 0; 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // For access to above function. 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot template <typename T> friend class GrTAllocator; 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static const int NUM_INIT_BLOCK_PTRS = 8; 215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkSTArray<NUM_INIT_BLOCK_PTRS, void*, true> fBlocks; 217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t fBlockSize; 218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t fItemSize; 219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fItemsPerBlock; 220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool fOwnFirstBlock; 221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fCount; 222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int fInsertionIndexInBlock; 223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot typedef SkNoncopyable INHERITED; 225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> class GrTAllocator; 228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> void* operator new(size_t, GrTAllocator<T>*); 229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> class GrTAllocator : SkNoncopyable { 231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot virtual ~GrTAllocator() { this->reset(); } 233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Create an allocator 236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @param itemsPerBlock the number of items to allocate at once 238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot explicit GrTAllocator(int itemsPerBlock) 240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fAllocator(sizeof(T), itemsPerBlock, nullptr) {} 241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Adds an item and returns it. 244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @return the added item. 246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot T& push_back() { 248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void* item = fAllocator.push_back(); 249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(item); 250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot new (item) T; 251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return *(T*)item; 252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot T& push_back(const T& t) { 255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void* item = fAllocator.push_back(); 256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(item); 257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot new (item) T(t); 258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return *(T*)item; 259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot template <typename... Args> T& emplace_back(Args&&... args) { 262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void* item = fAllocator.push_back(); 263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(item); 264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot new (item) T(std::forward<Args>(args)...); 265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return *(T*)item; 266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Remove the last item, only call if count() != 0 270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void pop_back() { 272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->back().~T(); 273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fAllocator.pop_back(); 274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Removes all added items. 278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void reset() { 280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int c = fAllocator.count(); 281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < c; ++i) { 282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ((T*)fAllocator[i])->~T(); 283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fAllocator.reset(); 285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Returns the item count. 289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count() const { 291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return fAllocator.count(); 292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Is the count 0? 296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool empty() const { return fAllocator.empty(); } 298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Access last item, only call if count() != 0 301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot T& back() { 303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return *(T*)fAllocator.back(); 304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Access last item, only call if count() != 0 308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const T& back() const { 310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return *(const T*)fAllocator.back(); 311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Iterates through the allocator. This is faster than using operator[] when walking linearly 315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * through the allocator. 316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot class Iter { 318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot public: 319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Initializes the iterator. next() must be called before get() or ops * and ->. 321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Iter(const GrTAllocator* allocator) : fImpl(&allocator->fAllocator) {} 323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Advances the iterator. Iteration is finished when next() returns false. 326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool next() { return fImpl.next(); } 328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Gets the current iterator value. Call next() at least once before calling. Don't call 331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * after next() returns false. 332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot T* get() const { return (T*) fImpl.get(); } 334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Convenience operators. Same rules for calling apply as get(). 337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot T& operator*() const { return *this->get(); } 339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot T* operator->() const { return this->get(); } 340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot private: 342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrAllocator::Iter fImpl; 343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Access item by index. 347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot T& operator[] (int i) { 349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return *(T*)(fAllocator[i]); 350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /** 353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Access item by index. 354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const T& operator[] (int i) const { 356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return *(const T*)(fAllocator[i]); 357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprotected: 360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /* 361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Set first block of memory to write into. Must be called before any other methods. 362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * @param initialBlock optional memory to use for the first block. 364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Must be at least size(T)*itemsPerBlock sized. 365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Caller is responsible for freeing this memory. 366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void setInitialBlock(void* initialBlock) { 368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fAllocator.setInitialBlock(initialBlock); 369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot friend void* operator new<T>(size_t, GrTAllocator*); 373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrAllocator fAllocator; 375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot typedef SkNoncopyable INHERITED; 376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <int N, typename T> class GrSTAllocator : public GrTAllocator<T> { 379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot typedef GrTAllocator<T> INHERITED; 381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot GrSTAllocator() : INHERITED(N) { 384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->setInitialBlock(fStorage.get()); 385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAlignedSTStorage<N, T> fStorage; 389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> void* operator new(size_t size, GrTAllocator<T>* allocator) { 392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return allocator->fAllocator.push_back(); 393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// Skia doesn't use C++ exceptions but it may be compiled with them enabled. Having an op delete 396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// to match the op new silences warnings about missing op delete when a constructor throws an 397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// exception. 398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottemplate <typename T> void operator delete(void*, GrTAllocator<T>*) { 399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SK_ABORT("Invalid Operation"); 400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define GrNEW_APPEND_TO_ALLOCATOR(allocator_ptr, type_name, args) \ 403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot new (allocator_ptr) type_name args 404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 406