Search code examples
c++stlallocator

How do I use microsoft's C++ allocators


I see on http://msdn.microsoft.com/en-us/library/ee292117.aspx and http://msdn.microsoft.com/en-us/library/ee292134.aspx that Microsoft provides macros and classes for specialized allocators, but I'm not sure what each of the caching strategies are, how to use them. Can someone explain when to use each of these parts?

  • Cache Templates
    • cache_freelist - The cache_freelist template class maintains a free list of memory blocks of size Sz. When the free list is full it uses operator delete to deallocate memory blocks. When the free list is empty it uses operator new to allocate new memory blocks. The maximum size of the free list is determined by the class max class passed in the Max parameter. Each memory block holds Sz bytes of usable memory and the data that operator new and operator delete require.
    • cache_suballoc - The cache_suballoc template class stores deallocated memory blocks in a free list with unbounded length, using freelist<sizeof(Type), max_unbounded>, and suballocates memory blocks from a larger chunk allocated with operator new when the free list is empty. Each chunk holds Sz * Nelts bytes of usable memory and the data that operator new and operator delete require. Allocated chunks are never freed.
    • cache_chunklist - This template class uses operator new to allocate chunks of raw memory, suballocating blocks to allocate storage for a memory block when needed; it stores deallocated memory blocks in a separate free list for each chunk, and uses operator delete to deallocate a chunk when none of its memory blocks is in use. Each memory block holds Sz bytes of usable memory and a pointer to the chunk that it belongs to. Each chunk holds Nelts memory blocks, three pointers, an int and the data that operator new and operator delete require.

I've written several allocators myself, but this documentation is just... confusing.


Solution

  • Wow, they really garbled the documentation, didn't they? (I wrote that code when I was at Dinkumware)

    The allocators here are policy-based: you can specify a caching policy and a synchronization policy.

    The basic idea is to make it easier to write allocators that use internal caches and can be synchronized across threads. There are half a dozen predefined allocators; their names all begin with allocator_. Use them if they fit your needs. In the MSDN stuff, look at the first paragraph of the description of the particular allocator; don't read the "Remarks", where they talk about ALLOCATOR_DECL;.

    You can also use that code to create your own allocators that use the pre-defined caching strategies (templates whose names begin with cache_) and synchronization strategies (templates whose names begin with sync_), or that use your own caching template and synchronization template. Getting a usable allocator from these pieces is a bit tedious, so the header provides ALLOCATOR_DECL as a convenient way to produce all the necessary boilerplate without having to write it yourself. ALLOCATOR_DECL takes three arguments: the name of the cache template to use, the name of the synchronization template to use, and the name of the allocator that you're creating. So instead of writing

    template <class T> class name
        : public Dinkum::allocators::allocator_base<T, sync<cache > >
        {
        public:
            name() {}
            template <class U> name(const name<U>&) {}
            template <class U> name& operator = (const name<U>&)
                {return *this; }
            template <class U> struct rebind
                {    /* convert a name<T> to a name<U> */
                typedef name<U> other;
                };
        };
    

    you would write ALLOCATOR_DECL(cache, sync, name);. allocator_base does the heavy lifting; the allocator itself has to be a derived type, so that it can handle rebind correctly. (The Dinkum in that code comes from the Dinkumware documentation; I don't know what namespace the Microsoft stuff puts these names in, but presumably the macro puts the right name there).

    For the cache templates:

    • cache_freelist maintains a linked list of node-sized blocks; the maximum size of the list is set by the template parameter Sz, and node allocation is managed with operator new and operator delete.
    • cache_suballoc adds another layer that manages a block of Nelts node blocks, all allocated as a single blob; allocation of a new element looks first to the free list, and if there is nothing free, allocates a new blob. Memory blocks are not deleted until the allocator is destroyed.
    • cache_chunklist allocates memory in blobs (like cache_suballoc), but doesn't use a common free list; when a block is released it goes back into the free list for its blob. When all of a blobs blocks have been released, the blob itself is deleted.