/*
* 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