diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/core/SkChunkAlloc.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/core/SkChunkAlloc.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,142 @@ +/* + * Copyright 2006 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkChunkAlloc.h" + +// Don't malloc any chunks smaller than this +#define MIN_CHUNKALLOC_BLOCK_SIZE 1024 + +// Return the new min blocksize given the current value +static size_t increase_next_size(size_t size) { + return size + (size >> 1); +} + +/////////////////////////////////////////////////////////////////////////////// + +struct SkChunkAlloc::Block { + Block* fNext; + size_t fFreeSize; + char* fFreePtr; + // data[] follows + + char* startOfData() { + return reinterpret_cast(this + 1); + } + + static void FreeChain(Block* block) { + while (block) { + Block* next = block->fNext; + sk_free(block); + block = next; + } + }; + + bool contains(const void* addr) const { + const char* ptr = reinterpret_cast(addr); + return ptr >= (const char*)(this + 1) && ptr < fFreePtr; + } +}; + +/////////////////////////////////////////////////////////////////////////////// + +SkChunkAlloc::SkChunkAlloc(size_t minSize) { + if (minSize < MIN_CHUNKALLOC_BLOCK_SIZE) { + minSize = MIN_CHUNKALLOC_BLOCK_SIZE; + } + + fBlock = NULL; + fMinSize = minSize; + fChunkSize = fMinSize; + fTotalCapacity = 0; + fTotalUsed = 0; + fBlockCount = 0; +} + +SkChunkAlloc::~SkChunkAlloc() { + this->reset(); +} + +void SkChunkAlloc::reset() { + Block::FreeChain(fBlock); + fBlock = NULL; + fChunkSize = fMinSize; // reset to our initial minSize + fTotalCapacity = 0; + fTotalUsed = 0; + fBlockCount = 0; +} + +SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) { + size_t size = bytes; + if (size < fChunkSize) { + size = fChunkSize; + } + + Block* block = (Block*)sk_malloc_flags(sizeof(Block) + size, + ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0); + + if (block) { + // block->fNext = fBlock; + block->fFreeSize = size; + block->fFreePtr = block->startOfData(); + + fTotalCapacity += size; + fBlockCount += 1; + + fChunkSize = increase_next_size(fChunkSize); + } + return block; +} + +void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) { + fTotalUsed += bytes; + + bytes = SkAlign4(bytes); + + Block* block = fBlock; + + if (block == NULL || bytes > block->fFreeSize) { + block = this->newBlock(bytes, ftype); + if (NULL == block) { + return NULL; + } + block->fNext = fBlock; + fBlock = block; + } + + SkASSERT(block && bytes <= block->fFreeSize); + char* ptr = block->fFreePtr; + + block->fFreeSize -= bytes; + block->fFreePtr = ptr + bytes; + return ptr; +} + +size_t SkChunkAlloc::unalloc(void* ptr) { + size_t bytes = 0; + Block* block = fBlock; + if (block) { + char* cPtr = reinterpret_cast(ptr); + char* start = block->startOfData(); + if (start <= cPtr && cPtr < block->fFreePtr) { + bytes = block->fFreePtr - cPtr; + block->fFreeSize += bytes; + block->fFreePtr = cPtr; + } + } + return bytes; +} + +bool SkChunkAlloc::contains(const void* addr) const { + const Block* block = fBlock; + while (block) { + if (block->contains(addr)) { + return true; + } + block = block->fNext; + } + return false; +}