14da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com/*
24da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com * Copyright 2012 Google Inc.
34da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com *
44da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com * Use of this source code is governed by a BSD-style license that can be
54da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com * found in the LICENSE file.
64da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com */
74da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com
84da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com#ifndef GrMemoryPool_DEFINED
94da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com#define GrMemoryPool_DEFINED
104da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com
114da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com#include "GrTypes.h"
124da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com
134da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com/**
144da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com * Allocates memory in blocks and parcels out space in the blocks for allocation
154da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com * requests. It is optimized for allocate / release speed over memory
164da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com * effeciency. The interface is designed to be used to implement operator new
174da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com * and delete overrides. All allocations are expected to be released before the
184da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com * pool's destructor is called. Allocations will be 8-byte aligned.
194da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com */
204da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.comclass GrMemoryPool {
214da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.compublic:
224da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    /**
234da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com     * Prealloc size is the amount of space to make available at pool creation
244da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com     * time and keep around until pool destruction. The min alloc size is the
254da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com     * smallest allowed size of additional allocations.
264da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com     */
274da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    GrMemoryPool(size_t preallocSize, size_t minAllocSize);
284da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com
294da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    ~GrMemoryPool();
304da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com
314da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    /**
324da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com     * Allocates memory. The memory must be freed with release().
334da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com     */
344da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    void* allocate(size_t size);
354da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com
364da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    /**
374da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com     * p must have been returned by allocate()
384da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com     */
394da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    void release(void* p);
404da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com
414da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    /**
424da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com     * Returns true if there are no unreleased allocations.
434da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com     */
444da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    bool isEmpty() const { return fTail == fHead && !fHead->fLiveCount; }
454da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com
46b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt    /**
47b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt     * Returns the total allocated size of the GrMemoryPool
48b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt     */
49b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt    size_t size() const { return fSize; }
50b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt
514da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.comprivate:
524da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    struct BlockHeader;
534da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com
548743b8f2a5e30af66f955519c90cd2cb841af95dcommit-bot@chromium.org    static BlockHeader* CreateBlock(size_t size);
554da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com
568743b8f2a5e30af66f955519c90cd2cb841af95dcommit-bot@chromium.org    static void DeleteBlock(BlockHeader* block);
574da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com
584da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    void validate();
594da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com
604da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    struct BlockHeader {
61dcba4c2cc30cc64f08def991376c6dab65cfb51ctomhudson@google.com        BlockHeader* fNext;      ///< doubly-linked list of blocks.
624da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com        BlockHeader* fPrev;
63dcba4c2cc30cc64f08def991376c6dab65cfb51ctomhudson@google.com        int          fLiveCount; ///< number of outstanding allocations in the
64dcba4c2cc30cc64f08def991376c6dab65cfb51ctomhudson@google.com                                 ///< block.
65dcba4c2cc30cc64f08def991376c6dab65cfb51ctomhudson@google.com        intptr_t     fCurrPtr;   ///< ptr to the start of blocks free space.
66dcba4c2cc30cc64f08def991376c6dab65cfb51ctomhudson@google.com        intptr_t     fPrevPtr;   ///< ptr to the last allocation made
67dcba4c2cc30cc64f08def991376c6dab65cfb51ctomhudson@google.com        size_t       fFreeSize;  ///< amount of free space left in the block.
68b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt        size_t       fSize;      ///< total allocated size of the block
694da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    };
704da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com
714da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    enum {
724da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com        // We assume this alignment is good enough for everybody.
734da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com        kAlignment    = 8,
744da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com        kHeaderSize   = GR_CT_ALIGN_UP(sizeof(BlockHeader), kAlignment),
754da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com        kPerAllocPad  = GR_CT_ALIGN_UP(sizeof(BlockHeader*), kAlignment),
764da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    };
77b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt    size_t                            fSize;
784da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    size_t                            fPreallocSize;
794da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    size_t                            fMinAllocSize;
804da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    BlockHeader*                      fHead;
814da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    BlockHeader*                      fTail;
82515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
834da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com    int                               fAllocationCnt;
84b7133bed55af8dd4ca9427892bb1a5623dbaccf0joshualitt    int                               fAllocBlockCnt;
854da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com#endif
864da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com};
874da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com
884da34e36cb7a07c3a28ae2a135b1837c26fc7aeabsalomon@google.com#endif
89