3
\$\begingroup\$

I have written a simple pool allocator for C++ and I'm looking for ways to improve it, in speed, usability or safety. For example, I don't know how to allocate a buffer larger than the pool size.

#pragma once

#include <limits>
#include <vector>

template<class T, size_t poolObjectCount = 100>
class PoolAllocator
{
public:
    template<class U>
    struct rebind
    {
        typedef PoolAllocator<U> other;
    };
private:
    const size_t m_poolSize = poolObjectCount * sizeof(T);
    std::vector<T*> m_pools;
    size_t m_nextObject = 0;


public:
    PoolAllocator()
    {
    allocateNewPool();
    }

    PoolAllocator(const PoolAllocator& other) = delete; // Copy is deleted

    PoolAllocator(PoolAllocator& other) = delete; // Copy is deleted


    PoolAllocator(PoolAllocator<T, poolObjectCount>&& other) noexcept
        :m_poolSize(std::move(other.m_poolSize)),             
    m_pools(std::move(other.m_pools)), m_nextObject(other.m_nextObject)
        {}

    PoolAllocator(const PoolAllocator<T, poolObjectCount>&& other) noexcept
        :m_poolSize(std::move(other.m_poolSize)),     
    m_pools(std::move(other.m_pools)), m_nextObject(other.m_nextObject)
    {}


    ~PoolAllocator()
    {
        while (!m_pools.empty())
        {
            T* backPool = m_pools.back();
            for (T* i = backPool + poolObjectCount - 1; i > backPool; i--)
                i->~T();
            operator delete((void *)backPool);
            m_pools.pop_back();
        }
    }

    T* allocate(size_t objectCount)
    {
        if (objectCount >= poolObjectCount)
            throw "Cannot allocate array greater than pool size";
        if (m_nextObject + objectCount >= poolObjectCount)
            allocateNewPool();

        T* returnValue = m_pools.back() + m_nextObject;
        m_nextObject++; 
        return returnValue;
    }

    template<class U = T>
    void construct(U * object)
    {
        new(object) U();
    }

    template<class U = T>
    void construct(U* object, const U& other)
    {
        new(object) U(other);
    }

    template<class U = T>
    void construct(U* object, U&& other)
    {
        new(object) U(other);
    }

    template<class U = T, class... ConstructorArguments>
    void construct(U* object, ConstructorArguments&& ...constructorArguments)
    {
        new(object) U(std::forward<ConstructorArguments>(constructorArguments)...);
    }


private:
    void allocateNewPool()
    {
    m_nextObject = 0;
    m_pools.emplace_back((T*)operator new(m_poolSize));
    }
};
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.