• 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 
containsSkChunkAlloc::Block53     bool contains(const void* addr) const {
54         const char* ptr = reinterpret_cast<const char*>(addr);
55         return ptr >= (const char*)(this + 1) && ptr < fFreePtr;
56     }
57 };
58 
SkChunkAlloc(size_t minSize)59 SkChunkAlloc::SkChunkAlloc(size_t minSize)
60     : fBlock(NULL), fMinSize(SkAlign4(minSize)), fPool(NULL), fTotalCapacity(0)
61 {
62 }
63 
~SkChunkAlloc()64 SkChunkAlloc::~SkChunkAlloc() {
65     this->reset();
66 }
67 
reset()68 void SkChunkAlloc::reset() {
69     fBlock->freeChain();
70     fBlock = NULL;
71     fPool->freeChain();
72     fPool = NULL;
73     fTotalCapacity = 0;
74 }
75 
reuse()76 void SkChunkAlloc::reuse() {
77     if (fPool && fBlock) {
78         fPool->tail()->fNext = fBlock;
79     }
80     fPool = fBlock;
81     fBlock = NULL;
82     fTotalCapacity = 0;
83 }
84 
newBlock(size_t bytes,AllocFailType ftype)85 SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) {
86     Block* block = fPool;
87 
88     if (block && bytes <= block->fFreeSize) {
89         fPool = block->fNext;
90         return block;
91     }
92 
93     size_t size = bytes;
94     if (size < fMinSize)
95         size = fMinSize;
96 
97     block = (Block*)sk_malloc_flags(sizeof(Block) + size,
98                         ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0);
99 
100     if (block) {
101         //    block->fNext = fBlock;
102         block->fFreeSize = size;
103         block->fFreePtr = block->startOfData();
104 
105         fTotalCapacity += size;
106     }
107     return block;
108 }
109 
alloc(size_t bytes,AllocFailType ftype)110 void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) {
111     bytes = SkAlign4(bytes);
112 
113     Block* block = fBlock;
114 
115     if (block == NULL || bytes > block->fFreeSize) {
116         block = this->newBlock(bytes, ftype);
117         if (NULL == block) {
118             return NULL;
119         }
120         block->fNext = fBlock;
121         fBlock = block;
122     }
123 
124     SkASSERT(block && bytes <= block->fFreeSize);
125     void* ptr = block->fFreePtr;
126 
127     block->fFreeSize -= bytes;
128     block->fFreePtr += bytes;
129     return ptr;
130 }
131 
unalloc(void * ptr)132 size_t SkChunkAlloc::unalloc(void* ptr) {
133     size_t bytes = 0;
134     Block* block = fBlock;
135     if (block) {
136         char* cPtr = reinterpret_cast<char*>(ptr);
137         char* start = block->startOfData();
138         if (start <= cPtr && cPtr < block->fFreePtr) {
139             bytes = block->fFreePtr - cPtr;
140             block->fFreeSize += bytes;
141             block->fFreePtr = cPtr;
142         }
143     }
144     return bytes;
145 }
146 
contains(const void * addr) const147 bool SkChunkAlloc::contains(const void* addr) const {
148     const Block* block = fBlock;
149     while (block) {
150         if (block->contains(addr)) {
151             return true;
152         }
153         block = block->fNext;
154     }
155     return false;
156 }
157 
158