1/*
2 * Copyright 2012 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#ifndef GrMemoryPool_DEFINED
9#define GrMemoryPool_DEFINED
10
11#include "GrTypes.h"
12
13/**
14 * Allocates memory in blocks and parcels out space in the blocks for allocation
15 * requests. It is optimized for allocate / release speed over memory
16 * effeciency. The interface is designed to be used to implement operator new
17 * and delete overrides. All allocations are expected to be released before the
18 * pool's destructor is called. Allocations will be 8-byte aligned.
19 */
20class GrMemoryPool {
21public:
22    /**
23     * Prealloc size is the amount of space to make available at pool creation
24     * time and keep around until pool destruction. The min alloc size is the
25     * smallest allowed size of additional allocations.
26     */
27    GrMemoryPool(size_t preallocSize, size_t minAllocSize);
28
29    ~GrMemoryPool();
30
31    /**
32     * Allocates memory. The memory must be freed with release().
33     */
34    void* allocate(size_t size);
35
36    /**
37     * p must have been returned by allocate()
38     */
39    void release(void* p);
40
41    /**
42     * Returns true if there are no unreleased allocations.
43     */
44    bool isEmpty() const { return fTail == fHead && !fHead->fLiveCount; }
45
46    /**
47     * Returns the total allocated size of the GrMemoryPool
48     */
49    size_t size() const { return fSize; }
50
51private:
52    struct BlockHeader;
53
54    static BlockHeader* CreateBlock(size_t size);
55
56    static void DeleteBlock(BlockHeader* block);
57
58    void validate();
59
60    struct BlockHeader {
61        BlockHeader* fNext;      ///< doubly-linked list of blocks.
62        BlockHeader* fPrev;
63        int          fLiveCount; ///< number of outstanding allocations in the
64                                 ///< block.
65        intptr_t     fCurrPtr;   ///< ptr to the start of blocks free space.
66        intptr_t     fPrevPtr;   ///< ptr to the last allocation made
67        size_t       fFreeSize;  ///< amount of free space left in the block.
68        size_t       fSize;      ///< total allocated size of the block
69    };
70
71    enum {
72        // We assume this alignment is good enough for everybody.
73        kAlignment    = 8,
74        kHeaderSize   = GR_CT_ALIGN_UP(sizeof(BlockHeader), kAlignment),
75        kPerAllocPad  = GR_CT_ALIGN_UP(sizeof(BlockHeader*), kAlignment),
76    };
77    size_t                            fSize;
78    size_t                            fPreallocSize;
79    size_t                            fMinAllocSize;
80    BlockHeader*                      fHead;
81    BlockHeader*                      fTail;
82#ifdef SK_DEBUG
83    int                               fAllocationCnt;
84    int                               fAllocBlockCnt;
85#endif
86};
87
88#endif
89