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) 32bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon , fOwnFirstBlock(NULL == 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. 195bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * This requires that you have passed NULL 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: 23213788bfbedc2528fbfa71162c888908c88f03ac2bsalomon@google.com 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) 2404b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com : fAllocator(sizeof(T), itemsPerBlock, NULL) {} 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); 250c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com SkNEW_PLACEMENT(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); 257c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com SkNEW_PLACEMENT_ARGS(item, T, (t)); 2584fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com return *(T*)item; 2594fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com } 2604fa6694c587b3830932429766c99d08c8dd9b723bsalomon@google.com 261ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 262a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon * Remove the last item, only call if count() != 0 263a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon */ 264a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon void pop_back() { 265a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon this->back().~T(); 266a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon fAllocator.pop_back(); 267a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon } 268a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon 269a1ae66d252edf6da932caed1fe43d11216e56c0ebsalomon /** 270bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Removes all added items. 271ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 272ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com void reset() { 2736a77cc5dde4bc01a0a9ba9ac32140146247d113fbsalomon@google.com int c = fAllocator.count(); 2746a77cc5dde4bc01a0a9ba9ac32140146247d113fbsalomon@google.com for (int i = 0; i < c; ++i) { 275ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com ((T*)fAllocator[i])->~T(); 276ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 277ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com fAllocator.reset(); 278ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 279d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 280ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 281bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Returns the item count. 282ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 2836a77cc5dde4bc01a0a9ba9ac32140146247d113fbsalomon@google.com int count() const { 284ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return fAllocator.count(); 285ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 286d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 287ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 288bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Is the count 0? 289ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 290ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com bool empty() const { return fAllocator.empty(); } 291d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 292ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 293bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Access last item, only call if count() != 0 294ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 295ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com T& back() { 296ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return *(T*)fAllocator.back(); 297ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 298ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 299ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 300bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Access last item, only call if count() != 0 301ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 302ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com const T& back() const { 303ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return *(const T*)fAllocator.back(); 304ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 305ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 306ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 307bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Iterates through the allocator. This is faster than using operator[] when walking linearly 308bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * through the allocator. 309bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon */ 310bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon class Iter { 311bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon public: 312bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon /** 313bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Initializes the iterator. next() must be called before get() or ops * and ->. 314bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon */ 315bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon Iter(const GrTAllocator* allocator) : fImpl(&allocator->fAllocator) {} 316bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 317bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon /** 318bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Advances the iterator. Iteration is finished when next() returns false. 319bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon */ 320bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon bool next() { return fImpl.next(); } 321bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 322bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon /** 323bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Gets the current iterator value. Call next() at least once before calling. Don't call 324bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * after next() returns false. 325bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon */ 326e1bc1c6958de768521323075b659d6ec6ad442fcbsalomon T* get() const { return (T*) fImpl.get(); } 327bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 328bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon /** 329bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Convenience operators. Same rules for calling apply as get(). 330bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon */ 331e1bc1c6958de768521323075b659d6ec6ad442fcbsalomon T& operator*() const { return *this->get(); } 332e1bc1c6958de768521323075b659d6ec6ad442fcbsalomon T* operator->() const { return this->get(); } 333bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 334bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon private: 335bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon GrAllocator::Iter fImpl; 336bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon }; 337bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon 338bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon /** 339bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Access item by index. 340d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com */ 3416a77cc5dde4bc01a0a9ba9ac32140146247d113fbsalomon@google.com T& operator[] (int i) { 342ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return *(T*)(fAllocator[i]); 343ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com } 344d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 345ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com /** 346bce3d6dbb91c3e67f1010556c2b8aaf6d7a49267bsalomon * Access item by index. 347ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com */ 3486a77cc5dde4bc01a0a9ba9ac32140146247d113fbsalomon@google.com const T& operator[] (int i) const { 349ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com return *(const T*)(fAllocator[i]); 3504b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com } 3514b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com 3524b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.comprotected: 353845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org /* 354845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org * Set first block of memory to write into. Must be called before any other methods. 355845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org * 356845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org * @param initialBlock optional memory to use for the first block. 357845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org * Must be at least size(T)*itemsPerBlock sized. 358845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org * Caller is responsible for freeing this memory. 359845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org */ 360845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org void setInitialBlock(void* initialBlock) { 361845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org fAllocator.setInitialBlock(initialBlock); 3624b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com } 3634b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com 3644b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.comprivate: 365b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon friend void* operator new<T>(size_t, GrTAllocator*); 366b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon 3674b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com GrAllocator fAllocator; 368a0b40280a49a8a43af7929ead3b3489951c58501commit-bot@chromium.org typedef SkNoncopyable INHERITED; 3694b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com}; 3704b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com 3714b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.comtemplate <int N, typename T> class GrSTAllocator : public GrTAllocator<T> { 3724b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.comprivate: 3734b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com typedef GrTAllocator<T> INHERITED; 3744b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com 3754b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.compublic: 376845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org GrSTAllocator() : INHERITED(N) { 377845da77bc04de38e3c410ee1e26d9df70ab7d0eecommit-bot@chromium.org this->setInitialBlock(fStorage.get()); 3784b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com } 3794b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com 3804b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.comprivate: 3814b90c62dfcda5866808ceedee46358b3d9792c93bsalomon@google.com SkAlignedSTStorage<N, T> fStorage; 382ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com}; 383ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com 384b3e3a955b6628acc540ef14854b57abb089e62dfbsalomontemplate <typename T> void* operator new(size_t size, GrTAllocator<T>* allocator) { 385b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon return allocator->fAllocator.push_back(); 386b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon} 387b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon 388b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon// Skia doesn't use C++ exceptions but it may be compiled with them enabled. Having an op delete 389b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon// to match the op new silences warnings about missing op delete when a constructor throws an 390b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon// exception. 391b3e3a955b6628acc540ef14854b57abb089e62dfbsalomontemplate <typename T> void operator delete(void*, GrTAllocator<T>*) { 392b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon SK_CRASH(); 393b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon} 394b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon 395b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon#define GrNEW_APPEND_TO_ALLOCATOR(allocator_ptr, type_name, args) \ 396b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon new (allocator_ptr) type_name args 397b3e3a955b6628acc540ef14854b57abb089e62dfbsalomon 398ac10a2d039c5d52eed66e27cbbc503ab523c1cd5reed@google.com#endif 399