180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2012 Google Inc.
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef GrMemoryPool_DEFINED
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define GrMemoryPool_DEFINED
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "GrTypes.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/**
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Allocates memory in blocks and parcels out space in the blocks for allocation
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * requests. It is optimized for allocate / release speed over memory
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * effeciency. The interface is designed to be used to implement operator new
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * and delete overrides. All allocations are expected to be released before the
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * pool's destructor is called. Allocations will be 8-byte aligned.
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass GrMemoryPool {
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * Prealloc size is the amount of space to make available at pool creation
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * time and keep around until pool destruction. The min alloc size is the
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * smallest allowed size of additional allocations.
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrMemoryPool(size_t preallocSize, size_t minAllocSize);
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ~GrMemoryPool();
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * Allocates memory. The memory must be freed with release().
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void* allocate(size_t size);
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * p must have been returned by allocate()
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void release(void* p);
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * Returns true if there are no unreleased allocations.
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool isEmpty() const { return fTail == fHead && !fHead->fLiveCount; }
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    struct BlockHeader;
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
49e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    static BlockHeader* CreateBlock(size_t size);
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
51e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    static void DeleteBlock(BlockHeader* block);
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void validate();
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    struct BlockHeader {
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        BlockHeader* fNext;      ///< doubly-linked list of blocks.
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        BlockHeader* fPrev;
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int          fLiveCount; ///< number of outstanding allocations in the
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                 ///< block.
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        intptr_t     fCurrPtr;   ///< ptr to the start of blocks free space.
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        intptr_t     fPrevPtr;   ///< ptr to the last allocation made
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t       fFreeSize;  ///< amount of free space left in the block.
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    };
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    enum {
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // We assume this alignment is good enough for everybody.
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        kAlignment    = 8,
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        kHeaderSize   = GR_CT_ALIGN_UP(sizeof(BlockHeader), kAlignment),
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        kPerAllocPad  = GR_CT_ALIGN_UP(sizeof(BlockHeader*), kAlignment),
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    };
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t                            fPreallocSize;
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t                            fMinAllocSize;
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    BlockHeader*                      fHead;
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    BlockHeader*                      fTail;
750a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#ifdef SK_DEBUG
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int                               fAllocationCnt;
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
81