• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* 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 
20 struct SkChunkAlloc::Block {
21     Block*  fNext;
22     size_t  fFreeSize;
23     char*   fFreePtr;
24     // data[] follows
25 
startOfDataSkChunkAlloc::Block26     char* startOfData() {
27         return reinterpret_cast<char*>(this + 1);
28     }
29 
freeChainSkChunkAlloc::Block30     void freeChain() {    // this can be null
31         Block* block = this;
32         while (block) {
33             Block* next = block->fNext;
34             sk_free(block);
35             block = next;
36         }
37     };
38 
tailSkChunkAlloc::Block39     Block* tail() {
40         Block* block = this;
41         if (block) {
42             for (;;) {
43                 Block* next = block->fNext;
44                 if (NULL == next) {
45                     break;
46                 }
47                 block = next;
48             }
49         }
50         return block;
51     }
52 };
53 
SkChunkAlloc(size_t minSize)54 SkChunkAlloc::SkChunkAlloc(size_t minSize)
55     : fBlock(NULL), fMinSize(SkAlign4(minSize)), fPool(NULL), fTotalCapacity(0)
56 {
57 }
58 
~SkChunkAlloc()59 SkChunkAlloc::~SkChunkAlloc() {
60     this->reset();
61 }
62 
reset()63 void SkChunkAlloc::reset() {
64     fBlock->freeChain();
65     fBlock = NULL;
66     fPool->freeChain();
67     fPool = NULL;
68     fTotalCapacity = 0;
69 }
70 
reuse()71 void SkChunkAlloc::reuse() {
72     if (fPool && fBlock) {
73         fPool->tail()->fNext = fBlock;
74     }
75     fPool = fBlock;
76     fBlock = NULL;
77     fTotalCapacity = 0;
78 }
79 
newBlock(size_t bytes,AllocFailType ftype)80 SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) {
81     Block* block = fPool;
82 
83     if (block && bytes <= block->fFreeSize) {
84         fPool = block->fNext;
85         return block;
86     }
87 
88     size_t  size = SkMax32((int32_t)bytes, (int32_t)fMinSize);
89 
90     block = (Block*)sk_malloc_flags(sizeof(Block) + size,
91                         ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0);
92 
93     if (block) {
94         //    block->fNext = fBlock;
95         block->fFreeSize = size;
96         block->fFreePtr = block->startOfData();
97 
98         fTotalCapacity += size;
99     }
100     return block;
101 }
102 
alloc(size_t bytes,AllocFailType ftype)103 void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) {
104     bytes = SkAlign4(bytes);
105 
106     Block* block = fBlock;
107 
108     if (block == NULL || bytes > block->fFreeSize) {
109         block = this->newBlock(bytes, ftype);
110         if (NULL == block) {
111             return NULL;
112         }
113         block->fNext = fBlock;
114         fBlock = block;
115     }
116 
117     SkASSERT(block && bytes <= block->fFreeSize);
118     void* ptr = block->fFreePtr;
119 
120     block->fFreeSize -= bytes;
121     block->fFreePtr += bytes;
122     return ptr;
123 }
124 
unalloc(void * ptr)125 size_t SkChunkAlloc::unalloc(void* ptr) {
126     size_t bytes = 0;
127     Block* block = fBlock;
128     if (block) {
129         char* cPtr = reinterpret_cast<char*>(ptr);
130         char* start = block->startOfData();
131         if (start <= cPtr && cPtr < block->fFreePtr) {
132             bytes = block->fFreePtr - cPtr;
133             block->fFreeSize += bytes;
134             block->fFreePtr = cPtr;
135         }
136     }
137     return bytes;
138 }
139 
140