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