michael@0: /* michael@0: * Copyright 2012 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef GrMemoryPool_DEFINED michael@0: #define GrMemoryPool_DEFINED michael@0: michael@0: #include "GrTypes.h" michael@0: michael@0: /** michael@0: * Allocates memory in blocks and parcels out space in the blocks for allocation michael@0: * requests. It is optimized for allocate / release speed over memory michael@0: * effeciency. The interface is designed to be used to implement operator new michael@0: * and delete overrides. All allocations are expected to be released before the michael@0: * pool's destructor is called. Allocations will be 8-byte aligned. michael@0: */ michael@0: class GrMemoryPool { michael@0: public: michael@0: /** michael@0: * Prealloc size is the amount of space to make available at pool creation michael@0: * time and keep around until pool destruction. The min alloc size is the michael@0: * smallest allowed size of additional allocations. michael@0: */ michael@0: GrMemoryPool(size_t preallocSize, size_t minAllocSize); michael@0: michael@0: ~GrMemoryPool(); michael@0: michael@0: /** michael@0: * Allocates memory. The memory must be freed with release(). michael@0: */ michael@0: void* allocate(size_t size); michael@0: michael@0: /** michael@0: * p must have been returned by allocate() michael@0: */ michael@0: void release(void* p); michael@0: michael@0: /** michael@0: * Returns true if there are no unreleased allocations. michael@0: */ michael@0: bool isEmpty() const { return fTail == fHead && !fHead->fLiveCount; } michael@0: michael@0: private: michael@0: struct BlockHeader; michael@0: michael@0: static BlockHeader* CreateBlock(size_t size); michael@0: michael@0: static void DeleteBlock(BlockHeader* block); michael@0: michael@0: void validate(); michael@0: michael@0: struct BlockHeader { michael@0: BlockHeader* fNext; ///< doubly-linked list of blocks. michael@0: BlockHeader* fPrev; michael@0: int fLiveCount; ///< number of outstanding allocations in the michael@0: ///< block. michael@0: intptr_t fCurrPtr; ///< ptr to the start of blocks free space. michael@0: intptr_t fPrevPtr; ///< ptr to the last allocation made michael@0: size_t fFreeSize; ///< amount of free space left in the block. michael@0: }; michael@0: michael@0: enum { michael@0: // We assume this alignment is good enough for everybody. michael@0: kAlignment = 8, michael@0: kHeaderSize = GR_CT_ALIGN_UP(sizeof(BlockHeader), kAlignment), michael@0: kPerAllocPad = GR_CT_ALIGN_UP(sizeof(BlockHeader*), kAlignment), michael@0: }; michael@0: size_t fPreallocSize; michael@0: size_t fMinAllocSize; michael@0: BlockHeader* fHead; michael@0: BlockHeader* fTail; michael@0: #ifdef SK_DEBUG michael@0: int fAllocationCnt; michael@0: #endif michael@0: }; michael@0: michael@0: #endif