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