1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2010 Google Inc. 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 7ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 8ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#ifndef GrAllocator_DEFINED 9ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#define GrAllocator_DEFINED 10ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 11ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#include "GrConfig.h" 12a0b40280a49a8a43af7929ead3b3489951c58501commit-bot@chromium.org#include "GrTypes.h" 1349313f6b4391d0f74ab1964c295634e8830680f6bsalomon@google.com#include "SkTArray.h" 14a0b40280a49a8a43af7929ead3b3489951c58501commit-bot@chromium.org#include "SkTypes.h" 15ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 16e3beb6bd7de7fa211681abbb0be58e80b19885e0commit-bot@chromium.orgclass GrAllocator : SkNoncopyable { 17ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.compublic: 18bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon ~GrAllocator() { this->reset(); } 19ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 20ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 21ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * Create an allocator 22ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * 23ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * @param itemSize the size of each item to allocate 24ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * @param itemsPerBlock the number of items to allocate at once 25ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * @param initialBlock optional memory to use for the first block. 26ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * Must be at least itemSize*itemsPerBlock sized. 27ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * Caller is responsible for freeing this memory. 28ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 29bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock) 30bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon : fItemSize(itemSize) 31bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon , fItemsPerBlock(itemsPerBlock) 3296fcdcc219d2a0d3579719b84b28bede76efba64halcanary , fOwnFirstBlock(nullptr == initialBlock) 33bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon , fCount(0) 34bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon , fInsertionIndexInBlock(0) { 35f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(itemsPerBlock > 0); 36ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fBlockSize = fItemSize * fItemsPerBlock; 37bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon if (fOwnFirstBlock) { 38bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon // This force us to allocate a new block on push_back(). 39bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon fInsertionIndexInBlock = fItemsPerBlock; 40bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon } else { 41bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon fBlocks.push_back() = initialBlock; 42bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon fInsertionIndexInBlock = 0; 43bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon } 44845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org } 45845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org 46ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 47ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * Adds an item and returns pointer to it. 48ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * 49ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * @return pointer to the added item. 50ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 514fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com void* push_back() { 52ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com // we always have at least one block 53bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon if (fItemsPerBlock == fInsertionIndexInBlock) { 54bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon fBlocks.push_back() = sk_malloc_throw(fBlockSize); 55bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon fInsertionIndexInBlock = 0; 56d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 57bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon void* ret = (char*)fBlocks.back() + fItemSize * fInsertionIndexInBlock; 58ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com ++fCount; 59bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon ++fInsertionIndexInBlock; 60ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return ret; 61ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 62ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 63ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 64a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon * Remove the last item, only call if count() != 0 65a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon */ 66a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon void pop_back() { 67a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon SkASSERT(fCount); 68a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon SkASSERT(fInsertionIndexInBlock > 0); 69a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon --fInsertionIndexInBlock; 70a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon --fCount; 71a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon if (0 == fInsertionIndexInBlock) { 72a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon // Never delete the first block 73a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon if (fBlocks.count() > 1) { 74a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon sk_free(fBlocks.back()); 75a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon fBlocks.pop_back(); 76a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon fInsertionIndexInBlock = fItemsPerBlock; 77a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon } 78a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon } 79a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon } 80a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon 81a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon /** 82bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Removes all added items. 83ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 84d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com void reset() { 85bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon int firstBlockToFree = fOwnFirstBlock ? 0 : 1; 86bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon for (int i = firstBlockToFree; i < fBlocks.count(); ++i) { 87939ca7ce860c5e80a4fdccc0dba5f7bfa29fef22reed@google.com sk_free(fBlocks[i]); 88ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 89ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com if (fOwnFirstBlock) { 90bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon fBlocks.reset(); 91bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon // This force us to allocate a new block on push_back(). 92bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon fInsertionIndexInBlock = fItemsPerBlock; 93bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon } else { 94bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon fBlocks.pop_back_n(fBlocks.count() - 1); 95bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon fInsertionIndexInBlock = 0; 96ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 97ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fCount = 0; 98ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 99ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 100ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 101bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Returns the item count. 102ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 1036a77cc5dde4bc01a0a9ba9ac32140146247d113fbsalomon@google.com int count() const { 104ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return fCount; 105ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 106d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 107ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 108bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Is the count 0? 109ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 110bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon bool empty() const { return 0 == fCount; } 111d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 112ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 113bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Access last item, only call if count() != 0 114ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 115ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com void* back() { 116f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(fCount); 117bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon SkASSERT(fInsertionIndexInBlock > 0); 118bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon return (char*)(fBlocks.back()) + (fInsertionIndexInBlock - 1) * fItemSize; 119ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 120d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 121ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 122bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Access last item, only call if count() != 0 123ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 124ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com const void* back() const { 125f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(fCount); 126bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon SkASSERT(fInsertionIndexInBlock > 0); 127bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon return (const char*)(fBlocks.back()) + (fInsertionIndexInBlock - 1) * fItemSize; 128ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 129d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 130bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon /** 131bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Iterates through the allocator. This is faster than using operator[] when walking linearly 132bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * through the allocator. 133bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon */ 134bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon class Iter { 135bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon public: 136bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon /** 137bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Initializes the iterator. next() must be called before get(). 138bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon */ 139bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon Iter(const GrAllocator* allocator) 140bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon : fAllocator(allocator) 141bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon , fBlockIndex(-1) 142bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon , fIndexInBlock(allocator->fItemsPerBlock - 1) 143bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon , fItemIndex(-1) {} 144bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 145bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon /** 146bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Advances the iterator. Iteration is finished when next() returns false. 147bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon */ 148bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon bool next() { 149bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon ++fIndexInBlock; 150bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon ++fItemIndex; 151bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon if (fIndexInBlock == fAllocator->fItemsPerBlock) { 152bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon ++fBlockIndex; 153bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon fIndexInBlock = 0; 154bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon } 155bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon return fItemIndex < fAllocator->fCount; 156bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon } 157bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 158bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon /** 159bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Gets the current iterator value. Call next() at least once before calling. Don't call 160bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * after next() returns false. 161bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon */ 162e1bc1c6958de768521323075b659d6ec6ad442fcbsalomon void* get() const { 163bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon SkASSERT(fItemIndex >= 0 && fItemIndex < fAllocator->fCount); 164bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon return (char*) fAllocator->fBlocks[fBlockIndex] + fIndexInBlock * fAllocator->fItemSize; 165bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon } 166bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 167bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon private: 168bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon const GrAllocator* fAllocator; 169bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon int fBlockIndex; 170bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon int fIndexInBlock; 171bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon int fItemIndex; 172bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon }; 173bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 174ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 175bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Access item by index. 176d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com */ 1776a77cc5dde4bc01a0a9ba9ac32140146247d113fbsalomon@google.com void* operator[] (int i) { 178f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(i >= 0 && i < fCount); 179d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com return (char*)fBlocks[i / fItemsPerBlock] + 180ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fItemSize * (i % fItemsPerBlock); 181ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 182ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 183ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 184bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Access item by index. 185d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com */ 1866a77cc5dde4bc01a0a9ba9ac32140146247d113fbsalomon@google.com const void* operator[] (int i) const { 187f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(i >= 0 && i < fCount); 188d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com return (const char*)fBlocks[i / fItemsPerBlock] + 189ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fItemSize * (i % fItemsPerBlock); 190ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 191ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 192bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomonprotected: 193bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon /** 194bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Set first block of memory to write into. Must be called before any other methods. 19596fcdcc219d2a0d3579719b84b28bede76efba64halcanary * This requires that you have passed nullptr in the constructor. 196bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * 197bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * @param initialBlock optional memory to use for the first block. 198bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Must be at least itemSize*itemsPerBlock sized. 199bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Caller is responsible for freeing this memory. 200bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon */ 201bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon void setInitialBlock(void* initialBlock) { 202bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon SkASSERT(0 == fCount); 203bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon SkASSERT(0 == fBlocks.count()); 204bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon SkASSERT(fItemsPerBlock == fInsertionIndexInBlock); 205bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon fOwnFirstBlock = false; 206bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon fBlocks.push_back() = initialBlock; 207bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon fInsertionIndexInBlock = 0; 208bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon } 209bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 210bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon // For access to above function. 211bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon template <typename T> friend class GrTAllocator; 212bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 213ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.comprivate: 2146a77cc5dde4bc01a0a9ba9ac32140146247d113fbsalomon@google.com static const int NUM_INIT_BLOCK_PTRS = 8; 215d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 216bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon SkSTArray<NUM_INIT_BLOCK_PTRS, void*, true> fBlocks; 217bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon size_t fBlockSize; 218bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon size_t fItemSize; 219bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon int fItemsPerBlock; 220bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon bool fOwnFirstBlock; 221bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon int fCount; 222bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon int fInsertionIndexInBlock; 2234b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com 224a0b40280a49a8a43af7929ead3b3489951c58501commit-bot@chromium.org typedef SkNoncopyable INHERITED; 225ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}; 226ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 227b3e3a955b6628acc540ef14854b57abb089e62dfbsalomontemplate <typename T> class GrTAllocator; 228b3e3a955b6628acc540ef14854b57abb089e62dfbsalomontemplate <typename T> void* operator new(size_t, GrTAllocator<T>*); 229b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon 230b3e3a955b6628acc540ef14854b57abb089e62dfbsalomontemplate <typename T> class GrTAllocator : SkNoncopyable { 231ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.compublic: 232fc6c37b981daeece7474ce61070c707c37eefa62Mike Klein virtual ~GrTAllocator() { this->reset(); } 233a55847ba22ae4a673af022e7d88404e080195464bsalomon@google.com 234ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 235ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * Create an allocator 236ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * 237ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * @param itemsPerBlock the number of items to allocate at once 238ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 2394b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com explicit GrTAllocator(int itemsPerBlock) 24096fcdcc219d2a0d3579719b84b28bede76efba64halcanary : fAllocator(sizeof(T), itemsPerBlock, nullptr) {} 241a55847ba22ae4a673af022e7d88404e080195464bsalomon@google.com 242a55847ba22ae4a673af022e7d88404e080195464bsalomon@google.com /** 243ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * Adds an item and returns it. 244ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * 245ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com * @return the added item. 246ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 247ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com T& push_back() { 248ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com void* item = fAllocator.push_back(); 24949f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(item); 250385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary new (item) T; 251ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return *(T*)item; 252ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 2534fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com 2544fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com T& push_back(const T& t) { 2554fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com void* item = fAllocator.push_back(); 25649f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(item); 257385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary new (item) T(t); 2584fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com return *(T*)item; 2594fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com } 2604fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com 261bc6b99d22e8d9f6543ffffdc846e40e8075046c5Brian Salomon template <typename... Args> T& emplace_back(Args&&... args) { 262bc6b99d22e8d9f6543ffffdc846e40e8075046c5Brian Salomon void* item = fAllocator.push_back(); 263bc6b99d22e8d9f6543ffffdc846e40e8075046c5Brian Salomon SkASSERT(item); 264bc6b99d22e8d9f6543ffffdc846e40e8075046c5Brian Salomon new (item) T(std::forward<Args>(args)...); 265bc6b99d22e8d9f6543ffffdc846e40e8075046c5Brian Salomon return *(T*)item; 266bc6b99d22e8d9f6543ffffdc846e40e8075046c5Brian Salomon } 267bc6b99d22e8d9f6543ffffdc846e40e8075046c5Brian Salomon 268ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 269a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon * Remove the last item, only call if count() != 0 270a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon */ 271a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon void pop_back() { 272a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon this->back().~T(); 273a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon fAllocator.pop_back(); 274a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon } 275a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon 276a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon /** 277bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Removes all added items. 278ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 279ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com void reset() { 2806a77cc5dde4bc01a0a9ba9ac32140146247d113fbsalomon@google.com int c = fAllocator.count(); 2816a77cc5dde4bc01a0a9ba9ac32140146247d113fbsalomon@google.com for (int i = 0; i < c; ++i) { 282ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com ((T*)fAllocator[i])->~T(); 283ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 284ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAllocator.reset(); 285ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 286d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 287ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 288bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Returns the item count. 289ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 2906a77cc5dde4bc01a0a9ba9ac32140146247d113fbsalomon@google.com int count() const { 291ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return fAllocator.count(); 292ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 293d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 294ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 295bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Is the count 0? 296ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 297ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com bool empty() const { return fAllocator.empty(); } 298d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 299ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 300bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Access last item, only call if count() != 0 301ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 302ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com T& back() { 303ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return *(T*)fAllocator.back(); 304ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 305ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 306ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 307bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Access last item, only call if count() != 0 308ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 309ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com const T& back() const { 310ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return *(const T*)fAllocator.back(); 311ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 312ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 313ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 314bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Iterates through the allocator. This is faster than using operator[] when walking linearly 315bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * through the allocator. 316bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon */ 317bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon class Iter { 318bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon public: 319bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon /** 320bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Initializes the iterator. next() must be called before get() or ops * and ->. 321bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon */ 322bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon Iter(const GrTAllocator* allocator) : fImpl(&allocator->fAllocator) {} 323bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 324bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon /** 325bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Advances the iterator. Iteration is finished when next() returns false. 326bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon */ 327bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon bool next() { return fImpl.next(); } 328bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 329bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon /** 330bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Gets the current iterator value. Call next() at least once before calling. Don't call 331bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * after next() returns false. 332bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon */ 333e1bc1c6958de768521323075b659d6ec6ad442fcbsalomon T* get() const { return (T*) fImpl.get(); } 334bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 335bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon /** 336bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Convenience operators. Same rules for calling apply as get(). 337bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon */ 338e1bc1c6958de768521323075b659d6ec6ad442fcbsalomon T& operator*() const { return *this->get(); } 339e1bc1c6958de768521323075b659d6ec6ad442fcbsalomon T* operator->() const { return this->get(); } 340bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 341bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon private: 342bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon GrAllocator::Iter fImpl; 343bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon }; 344bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 345bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon /** 346bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Access item by index. 347d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com */ 3486a77cc5dde4bc01a0a9ba9ac32140146247d113fbsalomon@google.com T& operator[] (int i) { 349ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return *(T*)(fAllocator[i]); 350ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 351d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 352ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 353bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Access item by index. 354ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 3556a77cc5dde4bc01a0a9ba9ac32140146247d113fbsalomon@google.com const T& operator[] (int i) const { 356ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return *(const T*)(fAllocator[i]); 3574b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com } 3584b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com 3594b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.comprotected: 360845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org /* 361845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org * Set first block of memory to write into. Must be called before any other methods. 362845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org * 363845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org * @param initialBlock optional memory to use for the first block. 364845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org * Must be at least size(T)*itemsPerBlock sized. 365845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org * Caller is responsible for freeing this memory. 366845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org */ 367845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org void setInitialBlock(void* initialBlock) { 368845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org fAllocator.setInitialBlock(initialBlock); 3694b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com } 3704b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com 3714b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.comprivate: 372b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon friend void* operator new<T>(size_t, GrTAllocator*); 373b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon 3744b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com GrAllocator fAllocator; 375a0b40280a49a8a43af7929ead3b3489951c58501commit-bot@chromium.org typedef SkNoncopyable INHERITED; 3764b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com}; 3774b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com 3784b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.comtemplate <int N, typename T> class GrSTAllocator : public GrTAllocator<T> { 3794b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.comprivate: 3804b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com typedef GrTAllocator<T> INHERITED; 3814b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com 3824b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.compublic: 383845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org GrSTAllocator() : INHERITED(N) { 384845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org this->setInitialBlock(fStorage.get()); 3854b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com } 3864b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com 3874b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.comprivate: 3884b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com SkAlignedSTStorage<N, T> fStorage; 389ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}; 390ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 391b3e3a955b6628acc540ef14854b57abb089e62dfbsalomontemplate <typename T> void* operator new(size_t size, GrTAllocator<T>* allocator) { 392b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon return allocator->fAllocator.push_back(); 393b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon} 394b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon 395b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon// Skia doesn't use C++ exceptions but it may be compiled with them enabled. Having an op delete 396b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon// to match the op new silences warnings about missing op delete when a constructor throws an 397b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon// exception. 398b3e3a955b6628acc540ef14854b57abb089e62dfbsalomontemplate <typename T> void operator delete(void*, GrTAllocator<T>*) { 399f2b340fc885ad2a12d2d73974eff9c8f4c94192cdjsollen SK_ABORT("Invalid Operation"); 400b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon} 401b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon 402b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon#define GrNEW_APPEND_TO_ALLOCATOR(allocator_ptr, type_name, args) \ 403b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon new (allocator_ptr) type_name args 404b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon 405ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif 406