具有realloc的自定义池内存分配器

时间:2019-01-25 08:56:15

标签: c++ memory memory-management pool entity-component-system

我正在创建pooled_allocator以在一个内存块中为特定类型的组件分配内存。如何更新存储在某个容器中的已分配的ptrs?

我使用通用方法为自己的游戏实施了ECS。我用过

std::unordered_map<TypeIndex, vector<BaseComponent*>>

按类型存储我的组件。

这就是我现在为组件分配内存的方式。

template<typename T, typename... Args>
T* Entity::assign(Args&&... args)
{
    //....
    // if there are no components of this type yet
    std::allocator<T> alloc;
    T* comp = std::allocator_traits<std::allocator<T>>::allocate(alloc, 1);

    std::allocator_traits<std::allocator<T>>::construct(alloc, comp, T(args...));

    // get container for type and add pointer to newly allocated component, that has to be stored in pool
    container.push_back(comp);
    components.insert({ getTypeIndex<T>(), container });
}

因此,现在我要实现一些pooled_allocator,它应该满足所有std :: allocator_traits要求,以将其用作组件的分配器。但是我想使其动态化,因此它应该能够扩展其内部内存块。

我现在有什么?

template<typename T, unsigned int Size = 10>
class pooled_allocator
{
    // some typedefs
    typedef value_type * pointer;

    static void* m_memoryBlock; // malloc(SIZE*Size) or nullptr to reproduce problem
    static std::list<MyBlockNode> m_allocated;
    static const size_t SIZE; // sizeof(T)

    // some methods

    static pointer allocate(const size_t amount)
    {
        if (!m_memoryBlock)
            m_memoryBlock = malloc(amount * SIZE);
        else
        {
            // here realloc can return another pointer
            m_memoryBlock = realloc(m_memoryBlock, m_allocated.size() * SIZE + amount * SIZE);         
        }

        int index = m_allocated.size();
        m_allocated.push_back(MyBlockNode { });

        pointer elPointer = (pointer)((pointer)m_memoryBlock + index * SIZE);

        return elPointer;
    }

    template <class Up, class... Args>
    void construct(Up* p, Args&&... args)
    {
       new((void*)p) Up(std::forward<Args>(args)...);
    }
}

问题是realloc将指针返回到另一个已分配块(不同的指针),该已分配对象已复制到新位置,并且存储在components [typeIndex()]中的所有指针变为无效(

我该如何解决?选项之一是返回一些ComponentHandle而不是T *,并且如果内部内存块已移动,请使用新的指针更新所有已返回的句柄,但是这会降低分配速度并产生一些限制。

我知道boost :: pool_allocator,但是我的游戏太小,无法集成这样的库。

1 个答案:

答案 0 :(得分:0)

您创建了这样的问题来定义自己的内存分配。

一种解决方案是不重新分配,而是在需要时分配一个新块,并管理所有这些块。

但是真正的问题是为什么你这样做吗?您可能选择了这种方式来解决另一个问题,哪个?