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  */
20 class GrMemoryPool {
21 public:
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      */
isEmpty()44     bool isEmpty() const { return fTail == fHead && !fHead->fLiveCount; }
45 
46     /**
47      * Returns the total allocated size of the GrMemoryPool
48      */
size()49     size_t size() const { return fSize; }
50 
51 private:
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