Memory 0.4: Polishing, Error handling, Storage, Traits, Documentation and more

It took a really long time - three months minus one day - but I have finally finished version 0.4 of foonathan/memory. The release contains a lot of changes and has more than doubled the number of commits.

Polishing

The interface is completely cleaned and I’ve got rid of the historically grown stuff. This required renaming or moving a lot of stuff, in particular:

I’ve also added some missing features I’ve noticed while writing the documentation. They are many tiny things like the ability to specify a Mutex at almost every class or alias or more default template arguments for other classes.

Error handling

Another thing polished are the error handling facilites. Before they were a mess of various exceptions and calls to assert(). Now they use a well-defined interface and exception types.

But those facilites are customizable using handler functions. This allows a user-defined error handling even if exception support is disabled.

Allocator storage and traits improvement

The old allocator adapters are completely changed in the implementation. A new allocator_storage class template takes a StoragePolicy and stores a RawAllocator using it. The adapters like allocator_adapter or allocator_reference are now simply aliases for the allocator_storage template with a given policy.

Type-erased storage has been added as well, the tag type any_allocator can be specified as RawAllocator everywhere it is stored by an allocator_reference, like in std_allocator, allocator_deleter or allocator_reference itself. It activates a specialization of allocator_reference that uses type-erasure to store a generic reference to any RawAllocator.

The default template specialization of allocator_traits has been overhauled, too. It is now able to handle a broader range of types including all Allocator classes! The minimum required interface for it has been reduced to allocate_node and deallocate_node only, the defaults in case of missing member functions are improved and there are better error messages if a type does not fulfill the criteria. The addition of supporting the Allocator concept allows passing an Allocator anywhere a RawAllocator is required.

Nodesize Debugger

The problem with pool allocators are that they require a node size. For example, if you want to use a std::list with a memory::memory_pool you write:

memory::memory_pool<> pool(???, 4096);
memory::list<int, decltype(pool)> list(pool);

At the point of ??? belongs the size of each node in the pool. But what should it be? 16? 32? It depends on the size of each node in the std::list of int. But the internal node size is not accessible, so there is no easy and portable way to get its size.

So I’ve added the nodesize_dbg. This tool debugs the node sizes of STL containers by passing them a custom allocator that tracks the size of the type it is rebound too. It automatically generates constants in the header container.hpp that contains the appropriate node sizes, allowing us to write:

memory::memory_pool<> pool(memory::list_node_size<int>::value, 4096);
memory::list<int, decltype(pool)> list(pool);

Other things worth mentioning

This blog post was written for my old blog design and ported over. If there are any issues, please let me know.