aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkChunkAlloc.cpp
diff options
context:
space:
mode:
authorGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2008-12-17 15:59:43 +0000
committerGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2008-12-17 15:59:43 +0000
commit8a1c16ff38322f0210116fa7293eb8817c7e477e (patch)
treefe40e07f6c8983318a2f79032b9a706ede1090c1 /src/core/SkChunkAlloc.cpp
parent2559c629078f738ac37095d896d580b681ac6a30 (diff)
grab from latest android
git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core/SkChunkAlloc.cpp')
-rw-r--r--src/core/SkChunkAlloc.cpp120
1 files changed, 120 insertions, 0 deletions
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;
+}
+