|
1 /* |
|
2 * Copyright 2010 Google Inc. |
|
3 * |
|
4 * Use of this source code is governed by a BSD-style license that can be |
|
5 * found in the LICENSE file. |
|
6 */ |
|
7 |
|
8 #include "GrAllocPool.h" |
|
9 |
|
10 #include "GrTypes.h" |
|
11 |
|
12 #define GrAllocPool_MIN_BLOCK_SIZE ((size_t)128) |
|
13 |
|
14 struct GrAllocPool::Block { |
|
15 Block* fNext; |
|
16 char* fPtr; |
|
17 size_t fBytesFree; |
|
18 size_t fBytesTotal; |
|
19 |
|
20 static Block* Create(size_t size, Block* next) { |
|
21 SkASSERT(size >= GrAllocPool_MIN_BLOCK_SIZE); |
|
22 |
|
23 Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size); |
|
24 block->fNext = next; |
|
25 block->fPtr = (char*)block + sizeof(Block); |
|
26 block->fBytesFree = size; |
|
27 block->fBytesTotal = size; |
|
28 return block; |
|
29 } |
|
30 |
|
31 bool canAlloc(size_t bytes) const { |
|
32 return bytes <= fBytesFree; |
|
33 } |
|
34 |
|
35 void* alloc(size_t bytes) { |
|
36 SkASSERT(bytes <= fBytesFree); |
|
37 fBytesFree -= bytes; |
|
38 void* ptr = fPtr; |
|
39 fPtr += bytes; |
|
40 return ptr; |
|
41 } |
|
42 |
|
43 size_t release(size_t bytes) { |
|
44 SkASSERT(bytes > 0); |
|
45 size_t free = GrMin(bytes, fBytesTotal - fBytesFree); |
|
46 fBytesFree += free; |
|
47 fPtr -= free; |
|
48 return bytes - free; |
|
49 } |
|
50 |
|
51 bool empty() const { return fBytesTotal == fBytesFree; } |
|
52 }; |
|
53 |
|
54 /////////////////////////////////////////////////////////////////////////////// |
|
55 |
|
56 GrAllocPool::GrAllocPool(size_t blockSize) { |
|
57 fBlock = NULL; |
|
58 fMinBlockSize = GrMax(blockSize, GrAllocPool_MIN_BLOCK_SIZE); |
|
59 SkDEBUGCODE(fBlocksAllocated = 0;) |
|
60 } |
|
61 |
|
62 GrAllocPool::~GrAllocPool() { |
|
63 this->reset(); |
|
64 } |
|
65 |
|
66 void GrAllocPool::reset() { |
|
67 this->validate(); |
|
68 |
|
69 Block* block = fBlock; |
|
70 while (block) { |
|
71 Block* next = block->fNext; |
|
72 sk_free(block); |
|
73 block = next; |
|
74 } |
|
75 fBlock = NULL; |
|
76 SkDEBUGCODE(fBlocksAllocated = 0;) |
|
77 } |
|
78 |
|
79 void* GrAllocPool::alloc(size_t size) { |
|
80 this->validate(); |
|
81 |
|
82 if (!fBlock || !fBlock->canAlloc(size)) { |
|
83 size_t blockSize = GrMax(fMinBlockSize, size); |
|
84 fBlock = Block::Create(blockSize, fBlock); |
|
85 SkDEBUGCODE(fBlocksAllocated += 1;) |
|
86 } |
|
87 return fBlock->alloc(size); |
|
88 } |
|
89 |
|
90 void GrAllocPool::release(size_t bytes) { |
|
91 this->validate(); |
|
92 |
|
93 while (bytes && NULL != fBlock) { |
|
94 bytes = fBlock->release(bytes); |
|
95 if (fBlock->empty()) { |
|
96 Block* next = fBlock->fNext; |
|
97 sk_free(fBlock); |
|
98 fBlock = next; |
|
99 SkDEBUGCODE(fBlocksAllocated -= 1;) |
|
100 } |
|
101 } |
|
102 } |
|
103 |
|
104 #ifdef SK_DEBUG |
|
105 |
|
106 void GrAllocPool::validate() const { |
|
107 Block* block = fBlock; |
|
108 int count = 0; |
|
109 while (block) { |
|
110 count += 1; |
|
111 block = block->fNext; |
|
112 } |
|
113 SkASSERT(fBlocksAllocated == count); |
|
114 } |
|
115 |
|
116 #endif |