Search code examples
c++containersallocator

Is it possible to use a custom allocator to allocate an arbitrary sized area?


I have a container class that manages the underlying memory in different chunks. The number of chunks varies with the number of objects stored in the container. I allocate a new chunk of memory whenever the container is about to exceed the currently available memory. And also, deallocate a chunk whenever it is no longer in use. So, the number chunks are variable during runtime. Therefore, I've to store the chunk pointers in a dynamically growing/shrinking array.

/*** Container Class ***/
template<class T, class Allocator = std::allocator<T>>
class CustomContainer{
public:    
    // Some member methods here..

private:
    void createNewChunk()
    {
        // Some code goes here ...

        newChunkAddr = new T*[CHUNK_SIZE];
    }

    void destroyChunk(T* chunkAddr)
    {
         // Some code goes here ...

         delete [] chunkAddr;
    }    

private:
    /*** Members ***/
    // Some other members ...
    std::size_t size        = 0;
    T**         chunks      = nullptr;
    Allocator   allocator;
};

Everything is well as long as the system that uses this container has a heap, thus a properly implemented operator new. The problem occurs when the system doesn't use the operator new and the user assumes that the container will allocate any dynamic resource using the Allocator it provides.

Immediately after a quick brainstorm, I thought that I can use the allocate method of the std::allocator_traits class for allocating the space required. Unfortunately, that method can only allocate areas of a size which is an exact multiple of the template value type used in the allocator. Here is the explanation of the corresponding function:

Uses the allocator a to allocate n*sizeof(Alloc::value_type) bytes of uninitialized storage. An array of type Alloc::value_type[n] is created in the storage, but none of its elements are constructed.

Here is the question, what is the proper way of allocating/deallocating the space for storing the chunk pointers?


Solution

  • what is the proper way of allocating/deallocating the space for storing the chunk pointers?

    Any correct way of allocating memory is a proper way. Each have their benefits and drawbacks. You should choose based on which benefits and drawbacks are important to your use case.

    You could use static storage if you wish to avoid dynamic storage, but that would limit your maximum number of chunks. Or if you don't mind dynamic storage, then you can use the global allocator.

    You could even let the user customise that allocation by providing a separate custom allocator.

    The way that standard containers do - which is also a proper way, but not the only proper way - is they would create a new allocator of type std::allocator_traits<Allocator>::rebind_alloc<T*>. If you do go the way of using separate custom allocators, this would be a reasonable default for the second allocator.

    I've to store the chunk pointers in a dynamically growing/shrinking array.

    There's a container for that purpose in the standard library: std::vector. You could use that within your container.


    P.S. Your the description of your container is quite similar to std::deque. Consider whether it would be simpler to just use that.