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