pool_allocator.h

Back to Pool allocator

pastel/sys/allocator/pool_allocator/

// Description: Pool allocator
// Detail: A uniform-sized memory allocator

#ifndef PASTELSYS_POOL_ALLOCATOR_H
#define PASTELSYS_POOL_ALLOCATOR_H

#include "pastel/sys/mytypes.h"

#include <boost/operators.hpp>

#include <set>

namespace Pastel
{

    //! A uniform sized memory allocator.
    /*!
   This allocator can be used to allocate constant
   sized memory blocks in a fast and cache friendly manner.
   This allocator avoids memory fragmentation by
   guaranteeing that if there is space available then
   it can also be allocated.
   */
    class PoolAllocator
        : boost::equality_comparable<
        PoolAllocator
        , boost::less_than_comparable<
        PoolAllocator
        > >
    {
    public:
        //! Constructs the allocator with the given unit size.
        /*!
       Preconditions:
       'unitSize' > 0

       Time complexity: constant
       Exception safety: strong
       */
        explicit PoolAllocator(integer unitSize);

        //! Destructs the allocator.
        /*!
       Time complexity: linear
       Exception safety: nothrow
       */
        ~PoolAllocator();

        //! Compares two allocators.
        /*!
       The allocators are compared by their
       memory address.

       Time complexity: constant
       Exception safety: nothrow
       */
        bool operator==(const PoolAllocator& that) const;

        //! Compares two allocators.
        /*!
       The allocators are compared by their
       memory address.

       Time complexity: constant
       Exception safety: nothrow
       */
        bool operator<(const PoolAllocator& that) const;

        //! Swaps two allocators.
        /*!
       Time complexity: constant
       Exception safety: nothrow
       */
        void swap(PoolAllocator& that);

        //! Frees all memory.
        /*!
       Time complexity: linear
       Exception safety: nothrow
       */
        void clear();

        //! Returns the unit size.
        /*!
       Time complexity: constant
       Exception safety: nothrow
       */
        integer unitSize() const;

        //! Returns the amount of requested memory.
        /*!
       Time complexity: constant
       Exception safety: nothrow
       */
        integer allocated() const;

        //! Returns the actual amount of allocated memory.
        /*!
       Time complexity: constant
       Exception safety: nothrow
       */
        integer capacity() const;

        //! Allocates unitSize-sized memory area.
        /*!
       Time complexity: amortized constant
       Exception safety: strong
       */
        void* allocate();

        //! Deallocates a previously allocated area.
        /*!
       Preconditions:
       'memAddress' != 0
       'memAddress' has been allocated from this allocator.

       Time complexity: logarithmic
       Exception safety: nothrow
       */
        void deallocate(const void* memAddress);

    private:
        PoolAllocator(const PoolAllocator& that) = delete;
        PoolAllocator& operator=(const PoolAllocator& that) = delete;

        struct Block
        {
            bool full() const
            {
                return unitsAllocated_ == unitsCapacity_;
            }

            uint8 firstFreeUnit_;
            uint8 unitsAllocated_;
            uint8 unitsCapacity_;
            uint8 padding_;
            Block* nextFreeBlock_;
            Block* previousFreeBlock_;
        };

        using Container = std::set<Block*>;
        using Iterator = Container::iterator;
        using ConstIterator = Container::const_iterator;

        void allocateBlock();
        Iterator deallocateBlock(const Iterator& that);
        Iterator searchBlock(uint8* memAddress);
        bool blockContains(const Block* block,
            const uint8* memAddress) const;
        void pushBackFreeBlock(Block* block);
        void removeFreeBlock(Block* block);

        integer unitSize_;
        integer unitsAllocated_;
        integer unitsCapacity_;
        Block* firstFreeBlock_;
        Block* lastFreeBlock_;
        integer freeBlocks_;
        Iterator deallocationBlock_;
        Container blockList_;
    };

    void swap(PoolAllocator& left, PoolAllocator& right);

}

#include "pastel/sys/allocator/pool_allocator/pool_allocator.hpp"

#endif