blob: ae37ec0839d59c6ae6405b191d068dbad3bac865 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* libs/corecg/SkChunkAlloc.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include "SkChunkAlloc.h"
19
20struct SkChunkAlloc::Block {
21 Block* fNext;
22 size_t fFreeSize;
23 char* fFreePtr;
24 // data[] follows
25
26 void freeChain() { // this can be null
27 Block* block = this;
28 while (block) {
29 Block* next = block->fNext;
30 sk_free(block);
31 block = next;
32 }
33 };
34
35 Block* tail() {
36 Block* block = this;
37 if (block) {
38 for (;;) {
39 Block* next = block->fNext;
40 if (NULL == next) {
41 break;
42 }
43 block = next;
44 }
45 }
46 return block;
47 }
48};
49
50SkChunkAlloc::SkChunkAlloc(size_t minSize)
51 : fBlock(NULL), fMinSize(SkAlign4(minSize)), fPool(NULL), fTotalCapacity(0)
52{
53}
54
55SkChunkAlloc::~SkChunkAlloc() {
56 this->reset();
57}
58
59void SkChunkAlloc::reset() {
60 fBlock->freeChain();
61 fBlock = NULL;
62 fPool->freeChain();
63 fPool = NULL;
64 fTotalCapacity = 0;
65}
66
67void SkChunkAlloc::reuse() {
68 if (fPool && fBlock) {
69 fPool->tail()->fNext = fBlock;
70 }
71 fPool = fBlock;
72 fBlock = NULL;
73 fTotalCapacity = 0;
74}
75
76SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) {
77 Block* block = fPool;
78
79 if (block && bytes <= block->fFreeSize) {
80 fPool = block->fNext;
81 return block;
82 }
83
84 size_t size = SkMax32((int32_t)bytes, (int32_t)fMinSize);
85
86 block = (Block*)sk_malloc_flags(sizeof(Block) + size,
87 ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0);
88
89 if (block) {
90 // block->fNext = fBlock;
91 block->fFreeSize = size;
92 block->fFreePtr = (char*)block + sizeof(Block);
93
94 fTotalCapacity += size;
95 }
96 return block;
97}
98
99void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) {
100 bytes = SkAlign4(bytes);
101
102 Block* block = fBlock;
103
104 if (block == NULL || bytes > block->fFreeSize) {
105 block = this->newBlock(bytes, ftype);
106 if (NULL == block) {
107 return NULL;
108 }
109 block->fNext = fBlock;
110 fBlock = block;
111 }
112
113 SkASSERT(block && bytes <= block->fFreeSize);
114 void* ptr = block->fFreePtr;
115
116 block->fFreeSize -= bytes;
117 block->fFreePtr += bytes;
118 return ptr;
119}
120