D on next-gen consoles and for game development

Sean Cavanaugh WorksOnMyMachine at gmail.com
Thu May 23 22:49:18 PDT 2013


On 5/24/2013 12:25 AM, deadalnix wrote:
> On Friday, 24 May 2013 at 00:44:14 UTC, Andrei Alexandrescu wrote:
>>> Custom allocators will probably be very useful, but if there's one thing
>>> STL has taught me, it's hard to use them effectively, and in practise,
>>> nobody ever uses them.
>>
>> Agreed.
>>
>
> To benefit from a custom allocator, you need to be under a very specific
> use case. Generic allocator are pretty good in most cases.


Most general allocators choke on multi-threaded code, so a large part of 
customizing allocations is to get rid lock contention.

While STL containers can have basic allocator templates assigned to 
them, if you really need performance you typically need to control all 
the different kinds of allocations a container does.

For example, a std::unordered_set allocates a ton of link list nodes to 
keep iterators stable inserts and removes, but the actual data payload 
is another separate allocation, as is some kind of root data structure 
to hold the hash tables.  In STL land this is all allocated through a 
single allocator object, making it very difficult (nearly impossible in 
a clean way) to allocate the payload data with some kind of fixed size 
block allocator, and allocate the metadata and link list nodes with a 
different allocator.  Some people would complain this exposes 
implementation details of a class, but the class is a template, it 
should be able to be configured to work the way you need it to.


class tHashMapNodeDefaultAllocator
{
public:
     static void* allocateMemory(size_t size, size_t alignment)
     {
         return mAlloc(size, alignment);
     }
     static void freeMemory(void* pointer) NOEXCEPT
     {
         mFree(pointer);
     }
};


template <typename DefaultKeyType, typename DefaultValueType>
class tHashMapConfiguration
{
public:
     typedef typename tHashClass<DefaultKeyType> HashClass;
     typedef typename tEqualsClass<DefaultKeyType> EqualClass;
     typedef tHashMapNodeDefaultAllocator NodeAllocator;
     typedef typename tDynamicArrayConfiguration<typename 
tHashMapNode<DefaultKeyType, DefaultValueType>> NodeArrayConfiguration;
};


template <typename KeyType, typename ValueType, typename 
HashMapConfiguration = tHashMapConfiguration<KeyType, ValueType>>
class tHashMap
{
};


// the tHashMap also has an array inside, so there is a way to configure 
that too:


class tDynamicArrayDefaultAllocator
{
public:
     static void* allocateMemory(size_t size, size_t alignment)
     {
         return mAlloc(size, alignment);
     }
     static void freeMemory(void* pointer) NOEXCEPT
     {
         mFree(pointer);
     }
};


class tDynamicArrayDefaultStrategy
{
public:
     static size_t nextAllocationSize(size_t currentSize, size_t 
objectSize, size_t numNewItemsRequested)
     {
         // return some size to grow the array by when the capacity is 
reached
         return currentSize + numNewItemsRequested * 2;
     }
}


template <typename DefaultObjectType>
class tDynamicArrayConfiguration
{
public:
     typedef tDynamicArrayDefaultStrategy DynamicArrayStrategy;
     typedef tDynamicArrayDefaultAllocator DynamicArrayAllocator;
};







More information about the Digitalmars-d mailing list