I want to write a custom memory manager/allocator for learning. I'm tempted to have a master allocator that requests n bytes of ram from the heap (via new). This would be followed by several allocator... Adaptors? Each would interface with the master, requesting a block of memory to manage, these would be stack, linear, pool, slab allocators etc each managing allocations from their slice of the master pool allocator.
The problem I have is whether I should write custom allocator_traits to interface with these for the various STL containers; or if I should just ignore the adaptor idea and simply overload new and delete to use the custom pool allocator/manager, the master one.
What I'm interested in understanding is what tangible benefit I would gain from having separate allocators for STL containers? It seems like the default std::allocator calls new and delete as needed so if I overload those to instead request from my big custom memory pool, I'd get all the benefit without the kruft of custom std::allocator code.
Or is this a matter where certain types of allocator models, like using a stack allocator for a std::deque would work better than the default allocator? And if so, wouldn't the normal stl implementation already specialise the default allocator for the various container types, or otherwise be optimised in the calls to the default allocator?
If it matters at all, I'm using C++20 via GCC 10+
Answering the two questions in-order:
Should I write custom allocator_traits to interface my allocators for the various STL containers?
Yes, for easy manipulations. Pretty soon in the implementation, situations such as controlling memory overlaps would arise. For example, while stress-testing the implementation at full capacity of individual allocators and figuring out an algorithm for re-allocation. In this regard, you would need to specialize the allocator_traits
class for the allocators rather than implement its member types
from scratch using new
and delete
operators.
The reason allocator_traits is used is because it facilitates easy handling of certain rules that need to be respected. Such rules occur all across memory management. [Refer here for three such rules during allocator construction.]
What tangible benefit I would gain from having separate allocators for STL containers?
Absolute control of how the master allocator assigns, re-assigns, copies, moves, and destructs memory (with added controls over quantifying/enhancing performance). Pretty cool, isn't it! If the default std allocator is used, you would loose this control and rely on a (albeit very good) default implementation of memory management.