1 2 /* 3 * Copyright 2010 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 11 #include "GrAllocPool.h" 12 13 #define GrAllocPool_MIN_BLOCK_SIZE ((size_t)128) 14 15 struct GrAllocPool::Block { 16 Block* fNext; 17 char* fPtr; 18 size_t fBytesFree; 19 size_t fBytesTotal; 20 21 static Block* Create(size_t size, Block* next) { 22 GrAssert(size >= GrAllocPool_MIN_BLOCK_SIZE); 23 24 Block* block = (Block*)GrMalloc(sizeof(Block) + size); 25 block->fNext = next; 26 block->fPtr = (char*)block + sizeof(Block); 27 block->fBytesFree = size; 28 block->fBytesTotal = size; 29 return block; 30 } 31 32 bool canAlloc(size_t bytes) const { 33 return bytes <= fBytesFree; 34 } 35 36 void* alloc(size_t bytes) { 37 GrAssert(bytes <= fBytesFree); 38 fBytesFree -= bytes; 39 void* ptr = fPtr; 40 fPtr += bytes; 41 return ptr; 42 } 43 44 size_t release(size_t bytes) { 45 GrAssert(bytes > 0); 46 size_t free = GrMin(bytes, fBytesTotal - fBytesFree); 47 fBytesFree += free; 48 fPtr -= free; 49 return bytes - free; 50 } 51 52 bool empty() const { return fBytesTotal == fBytesFree; } 53 }; 54 55 /////////////////////////////////////////////////////////////////////////////// 56 57 GrAllocPool::GrAllocPool(size_t blockSize) { 58 fBlock = NULL; 59 fMinBlockSize = GrMax(blockSize, GrAllocPool_MIN_BLOCK_SIZE); 60 GR_DEBUGCODE(fBlocksAllocated = 0;) 61 } 62 63 GrAllocPool::~GrAllocPool() { 64 this->reset(); 65 } 66 67 void GrAllocPool::reset() { 68 this->validate(); 69 70 Block* block = fBlock; 71 while (block) { 72 Block* next = block->fNext; 73 GrFree(block); 74 block = next; 75 } 76 fBlock = NULL; 77 GR_DEBUGCODE(fBlocksAllocated = 0;) 78 } 79 80 void* GrAllocPool::alloc(size_t size) { 81 this->validate(); 82 83 if (!fBlock || !fBlock->canAlloc(size)) { 84 size_t blockSize = GrMax(fMinBlockSize, size); 85 fBlock = Block::Create(blockSize, fBlock); 86 GR_DEBUGCODE(fBlocksAllocated += 1;) 87 } 88 return fBlock->alloc(size); 89 } 90 91 void GrAllocPool::release(size_t bytes) { 92 this->validate(); 93 94 while (bytes && NULL != fBlock) { 95 bytes = fBlock->release(bytes); 96 if (fBlock->empty()) { 97 Block* next = fBlock->fNext; 98 GrFree(fBlock); 99 fBlock = next; 100 GR_DEBUGCODE(fBlocksAllocated -= 1;) 101 } 102 } 103 } 104 105 106 #if GR_DEBUG 107 108 void GrAllocPool::validate() const { 109 Block* block = fBlock; 110 int count = 0; 111 while (block) { 112 count += 1; 113 block = block->fNext; 114 } 115 GrAssert(fBlocksAllocated == count); 116 } 117 118 #endif 119