• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2006 The Android Open Source Project
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #include "SkChunkAlloc.h"
11 
12 struct SkChunkAlloc::Block {
13     Block*  fNext;
14     size_t  fFreeSize;
15     char*   fFreePtr;
16     // data[] follows
17 
startOfDataSkChunkAlloc::Block18     char* startOfData() {
19         return reinterpret_cast<char*>(this + 1);
20     }
21 
freeChainSkChunkAlloc::Block22     void freeChain() {    // this can be null
23         Block* block = this;
24         while (block) {
25             Block* next = block->fNext;
26             sk_free(block);
27             block = next;
28         }
29     };
30 
tailSkChunkAlloc::Block31     Block* tail() {
32         Block* block = this;
33         if (block) {
34             for (;;) {
35                 Block* next = block->fNext;
36                 if (NULL == next) {
37                     break;
38                 }
39                 block = next;
40             }
41         }
42         return block;
43     }
44 
containsSkChunkAlloc::Block45     bool contains(const void* addr) const {
46         const char* ptr = reinterpret_cast<const char*>(addr);
47         return ptr >= (const char*)(this + 1) && ptr < fFreePtr;
48     }
49 };
50 
SkChunkAlloc(size_t minSize)51 SkChunkAlloc::SkChunkAlloc(size_t minSize)
52     : fBlock(NULL), fMinSize(SkAlign4(minSize)), fPool(NULL), fTotalCapacity(0)
53 {
54 }
55 
~SkChunkAlloc()56 SkChunkAlloc::~SkChunkAlloc() {
57     this->reset();
58 }
59 
reset()60 void SkChunkAlloc::reset() {
61     fBlock->freeChain();
62     fBlock = NULL;
63     fPool->freeChain();
64     fPool = NULL;
65     fTotalCapacity = 0;
66 }
67 
reuse()68 void SkChunkAlloc::reuse() {
69     if (fPool && fBlock) {
70         fPool->tail()->fNext = fBlock;
71     }
72     fPool = fBlock;
73     fBlock = NULL;
74     fTotalCapacity = 0;
75 }
76 
newBlock(size_t bytes,AllocFailType ftype)77 SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) {
78     Block* block = fPool;
79 
80     if (block && bytes <= block->fFreeSize) {
81         fPool = block->fNext;
82         return block;
83     }
84 
85     size_t size = bytes;
86     if (size < fMinSize)
87         size = fMinSize;
88 
89     block = (Block*)sk_malloc_flags(sizeof(Block) + size,
90                         ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0);
91 
92     if (block) {
93         //    block->fNext = fBlock;
94         block->fFreeSize = size;
95         block->fFreePtr = block->startOfData();
96 
97         fTotalCapacity += size;
98     }
99     return block;
100 }
101 
alloc(size_t bytes,AllocFailType ftype)102 void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) {
103     bytes = SkAlign4(bytes);
104 
105     Block* block = fBlock;
106 
107     if (block == NULL || bytes > block->fFreeSize) {
108         block = this->newBlock(bytes, ftype);
109         if (NULL == block) {
110             return NULL;
111         }
112         block->fNext = fBlock;
113         fBlock = block;
114     }
115 
116     SkASSERT(block && bytes <= block->fFreeSize);
117     void* ptr = block->fFreePtr;
118 
119     block->fFreeSize -= bytes;
120     block->fFreePtr += bytes;
121     return ptr;
122 }
123 
unalloc(void * ptr)124 size_t SkChunkAlloc::unalloc(void* ptr) {
125     size_t bytes = 0;
126     Block* block = fBlock;
127     if (block) {
128         char* cPtr = reinterpret_cast<char*>(ptr);
129         char* start = block->startOfData();
130         if (start <= cPtr && cPtr < block->fFreePtr) {
131             bytes = block->fFreePtr - cPtr;
132             block->fFreeSize += bytes;
133             block->fFreePtr = cPtr;
134         }
135     }
136     return bytes;
137 }
138 
contains(const void * addr) const139 bool SkChunkAlloc::contains(const void* addr) const {
140     const Block* block = fBlock;
141     while (block) {
142         if (block->contains(addr)) {
143             return true;
144         }
145         block = block->fNext;
146     }
147     return false;
148 }
149 
150