From 8a1c16ff38322f0210116fa7293eb8817c7e477e Mon Sep 17 00:00:00 2001 From: "reed@android.com" Date: Wed, 17 Dec 2008 15:59:43 +0000 Subject: grab from latest android git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/core/SkChunkAlloc.cpp | 120 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/core/SkChunkAlloc.cpp (limited to 'src/core/SkChunkAlloc.cpp') diff --git a/src/core/SkChunkAlloc.cpp b/src/core/SkChunkAlloc.cpp new file mode 100644 index 0000000000..ae37ec0839 --- /dev/null +++ b/src/core/SkChunkAlloc.cpp @@ -0,0 +1,120 @@ +/* libs/corecg/SkChunkAlloc.cpp +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include "SkChunkAlloc.h" + +struct SkChunkAlloc::Block { + Block* fNext; + size_t fFreeSize; + char* fFreePtr; + // data[] follows + + void freeChain() { // this can be null + Block* block = this; + while (block) { + Block* next = block->fNext; + sk_free(block); + block = next; + } + }; + + Block* tail() { + Block* block = this; + if (block) { + for (;;) { + Block* next = block->fNext; + if (NULL == next) { + break; + } + block = next; + } + } + return block; + } +}; + +SkChunkAlloc::SkChunkAlloc(size_t minSize) + : fBlock(NULL), fMinSize(SkAlign4(minSize)), fPool(NULL), fTotalCapacity(0) +{ +} + +SkChunkAlloc::~SkChunkAlloc() { + this->reset(); +} + +void SkChunkAlloc::reset() { + fBlock->freeChain(); + fBlock = NULL; + fPool->freeChain(); + fPool = NULL; + fTotalCapacity = 0; +} + +void SkChunkAlloc::reuse() { + if (fPool && fBlock) { + fPool->tail()->fNext = fBlock; + } + fPool = fBlock; + fBlock = NULL; + fTotalCapacity = 0; +} + +SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) { + Block* block = fPool; + + if (block && bytes <= block->fFreeSize) { + fPool = block->fNext; + return block; + } + + size_t size = SkMax32((int32_t)bytes, (int32_t)fMinSize); + + 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 = (char*)block + sizeof(Block); + + fTotalCapacity += size; + } + return block; +} + +void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) { + 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); + void* ptr = block->fFreePtr; + + block->fFreeSize -= bytes; + block->fFreePtr += bytes; + return ptr; +} + -- cgit v1.2.3