michael@0: /* michael@0: * Copyright 2010 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #include "GrAllocPool.h" michael@0: michael@0: #include "GrTypes.h" michael@0: michael@0: #define GrAllocPool_MIN_BLOCK_SIZE ((size_t)128) michael@0: michael@0: struct GrAllocPool::Block { michael@0: Block* fNext; michael@0: char* fPtr; michael@0: size_t fBytesFree; michael@0: size_t fBytesTotal; michael@0: michael@0: static Block* Create(size_t size, Block* next) { michael@0: SkASSERT(size >= GrAllocPool_MIN_BLOCK_SIZE); michael@0: michael@0: Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size); michael@0: block->fNext = next; michael@0: block->fPtr = (char*)block + sizeof(Block); michael@0: block->fBytesFree = size; michael@0: block->fBytesTotal = size; michael@0: return block; michael@0: } michael@0: michael@0: bool canAlloc(size_t bytes) const { michael@0: return bytes <= fBytesFree; michael@0: } michael@0: michael@0: void* alloc(size_t bytes) { michael@0: SkASSERT(bytes <= fBytesFree); michael@0: fBytesFree -= bytes; michael@0: void* ptr = fPtr; michael@0: fPtr += bytes; michael@0: return ptr; michael@0: } michael@0: michael@0: size_t release(size_t bytes) { michael@0: SkASSERT(bytes > 0); michael@0: size_t free = GrMin(bytes, fBytesTotal - fBytesFree); michael@0: fBytesFree += free; michael@0: fPtr -= free; michael@0: return bytes - free; michael@0: } michael@0: michael@0: bool empty() const { return fBytesTotal == fBytesFree; } michael@0: }; michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: GrAllocPool::GrAllocPool(size_t blockSize) { michael@0: fBlock = NULL; michael@0: fMinBlockSize = GrMax(blockSize, GrAllocPool_MIN_BLOCK_SIZE); michael@0: SkDEBUGCODE(fBlocksAllocated = 0;) michael@0: } michael@0: michael@0: GrAllocPool::~GrAllocPool() { michael@0: this->reset(); michael@0: } michael@0: michael@0: void GrAllocPool::reset() { michael@0: this->validate(); michael@0: michael@0: Block* block = fBlock; michael@0: while (block) { michael@0: Block* next = block->fNext; michael@0: sk_free(block); michael@0: block = next; michael@0: } michael@0: fBlock = NULL; michael@0: SkDEBUGCODE(fBlocksAllocated = 0;) michael@0: } michael@0: michael@0: void* GrAllocPool::alloc(size_t size) { michael@0: this->validate(); michael@0: michael@0: if (!fBlock || !fBlock->canAlloc(size)) { michael@0: size_t blockSize = GrMax(fMinBlockSize, size); michael@0: fBlock = Block::Create(blockSize, fBlock); michael@0: SkDEBUGCODE(fBlocksAllocated += 1;) michael@0: } michael@0: return fBlock->alloc(size); michael@0: } michael@0: michael@0: void GrAllocPool::release(size_t bytes) { michael@0: this->validate(); michael@0: michael@0: while (bytes && NULL != fBlock) { michael@0: bytes = fBlock->release(bytes); michael@0: if (fBlock->empty()) { michael@0: Block* next = fBlock->fNext; michael@0: sk_free(fBlock); michael@0: fBlock = next; michael@0: SkDEBUGCODE(fBlocksAllocated -= 1;) michael@0: } michael@0: } michael@0: } michael@0: michael@0: #ifdef SK_DEBUG michael@0: michael@0: void GrAllocPool::validate() const { michael@0: Block* block = fBlock; michael@0: int count = 0; michael@0: while (block) { michael@0: count += 1; michael@0: block = block->fNext; michael@0: } michael@0: SkASSERT(fBlocksAllocated == count); michael@0: } michael@0: michael@0: #endif