C++11 memory pool design pattern?

前端 未结 5 416
鱼传尺愫
鱼传尺愫 2020-12-07 13:34

I have a program that contains a processing phase that needs to use a bunch of different object instances (all allocated on the heap) from a tree of polymorphic types, all e

5条回答
  •  盖世英雄少女心
    2020-12-07 14:24

    This sounds what I have heard called a Linear Allocator. I will explain the basics of how I understand how it works.

    1. Allocate a block of memory using ::operator new(size);
    2. Have a void* that is your Pointer to the next free space in memory.
    3. You will have an alloc(size_t size) function that will give you a pointer to the location in the block from step one for you to construct on to using Placement New
    4. Placement new looks like... int* i = new(location)int(); where location is a void* to a block of memory you alloced from the allocator.
    5. when you are done with all of your memory you will call a Flush() function that will dealloc the memory from the pool or at least wipe the data clean.

    I programmed one of these recently and i will post my code here for you as well as do my best to explain.

        #include 
        class LinearAllocator:public ObjectBase
        {
        public:
            LinearAllocator();
            LinearAllocator(Pool* pool,size_t size);
            ~LinearAllocator();
            void* Alloc(Size_t size);
            void Flush();
        private:
            void** m_pBlock;
            void* m_pHeadFree;
            void* m_pEnd;
        };
    

    don't worry about what i'm inheriting from. i have been using this allocator in conjunction with a memory pool. but basically instead of getting the memory from operator new i am getting memory from a memory pool. the internal workings are the same essentially.

    Here is the implementation:

    LinearAllocator::LinearAllocator():ObjectBase::ObjectBase()
    {
        m_pBlock = nullptr;
        m_pHeadFree = nullptr;
        m_pEnd=nullptr;
    }
    
    LinearAllocator::LinearAllocator(Pool* pool,size_t size):ObjectBase::ObjectBase(pool)
    {
        if (pool!=nullptr) {
            m_pBlock = ObjectBase::AllocFromPool(size);
            m_pHeadFree = * m_pBlock;
            m_pEnd = (void*)((unsigned char*)*m_pBlock+size);
        }
        else{
            m_pBlock = nullptr;
            m_pHeadFree = nullptr;
            m_pEnd=nullptr;
        }
    }
    LinearAllocator::~LinearAllocator()
    {
        if (m_pBlock!=nullptr) {
            ObjectBase::FreeFromPool(m_pBlock);
        }
        m_pBlock = nullptr;
        m_pHeadFree = nullptr;
        m_pEnd=nullptr;
    }
    MemoryBlock* LinearAllocator::Alloc(size_t size)
    {
        if (m_pBlock!=nullptr) {
            void* test = (void*)((unsigned char*)m_pEnd-size);
            if (m_pHeadFree<=test) {
                void* temp = m_pHeadFree;
                m_pHeadFree=(void*)((unsigned char*)m_pHeadFree+size);
                return temp;
            }else{
                return nullptr;
            }
        }else return nullptr;
    }
    void LinearAllocator::Flush()
    {
        if (m_pBlock!=nullptr) {
            m_pHeadFree=m_pBlock;
            size_t size = (unsigned char*)m_pEnd-(unsigned char*)*m_pBlock;
            memset(*m_pBlock,0,size);
        }
    }
    

    This code is fully functional except for a few lines which will need to be changed because of my inheritance and use of the memory pool. but I bet you can figure out what needs to change and just let me know if you need a hand changing the code. This code has not been tested in any sort of professional manor and is not guaranteed to be thread safe or anything fancy like that. i just whipped it up and thought i could share it with you since you seemed to need help.

    I also have a working implementation of a fully generic memory pool if you think it may help you. I can explain how it works if you need.

    Once again if you need any help let me know. Good luck.

提交回复
热议问题