aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrAllocPool.cpp
blob: ecd2acfa05b464b5642fb426309d0b808c20e72b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

/*
 * Copyright 2010 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */



#include "GrAllocPool.h"

#define GrAllocPool_MIN_BLOCK_SIZE      ((size_t)128)

struct GrAllocPool::Block {
    Block*  fNext;
    char*   fPtr;
    size_t  fBytesFree;
    size_t  fBytesTotal;

    static Block* Create(size_t size, Block* next) {
        GrAssert(size >= GrAllocPool_MIN_BLOCK_SIZE);

        Block* block = (Block*)GrMalloc(sizeof(Block) + size);
        block->fNext = next;
        block->fPtr = (char*)block + sizeof(Block);
        block->fBytesFree = size;
        block->fBytesTotal = size;
        return block;
    }

    bool canAlloc(size_t bytes) const {
        return bytes <= fBytesFree;
    }

    void* alloc(size_t bytes) {
        GrAssert(bytes <= fBytesFree);
        fBytesFree -= bytes;
        void* ptr = fPtr;
        fPtr += bytes;
        return ptr;
    }
    
    size_t release(size_t bytes) {
        GrAssert(bytes > 0);
        size_t free = GrMin(bytes, fBytesTotal - fBytesFree);
        fBytesFree += free;
        fPtr -= free;
        return bytes - free;
    }
    
    bool empty() const { return fBytesTotal == fBytesFree; }
};

///////////////////////////////////////////////////////////////////////////////

GrAllocPool::GrAllocPool(size_t blockSize) {
    fBlock = NULL;
    fMinBlockSize = GrMax(blockSize, GrAllocPool_MIN_BLOCK_SIZE);
    GR_DEBUGCODE(fBlocksAllocated = 0;)
}

GrAllocPool::~GrAllocPool() {
    this->reset();
}

void GrAllocPool::reset() {
    this->validate();

    Block* block = fBlock;
    while (block) {
        Block* next = block->fNext;
        GrFree(block);
        block = next;
    }
    fBlock = NULL;
    GR_DEBUGCODE(fBlocksAllocated = 0;)
}

void* GrAllocPool::alloc(size_t size) {
    this->validate();
    
    if (!fBlock || !fBlock->canAlloc(size)) {
        size_t blockSize = GrMax(fMinBlockSize, size);
        fBlock = Block::Create(blockSize, fBlock);
        GR_DEBUGCODE(fBlocksAllocated += 1;)
    }
    return fBlock->alloc(size);
}

void GrAllocPool::release(size_t bytes) {
    this->validate();
    
    while (bytes && NULL != fBlock) {
        bytes = fBlock->release(bytes);
        if (fBlock->empty()) {
            Block* next = fBlock->fNext;
            GrFree(fBlock);
            fBlock = next;
            GR_DEBUGCODE(fBlocksAllocated -= 1;)
        }
    }
}


#if GR_DEBUG

void GrAllocPool::validate() const {
    Block* block = fBlock;
    int count = 0;
    while (block) {
        count += 1;
        block = block->fNext;
    }
    GrAssert(fBlocksAllocated == count);
}

#endif