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 <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
    {
    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
       */
        inline auto 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