Interesting PRs: bringing type system legitimacy to shared allocators

Stanislav Blinov via Digitalmars-d digitalmars-d at puremagic.com
Mon May 1 19:51:02 PDT 2017


On Monday, 1 May 2017 at 16:31:10 UTC, Nick Sabalausky (Abscissa) 
wrote:

> If we had a type similar to TaggedAlgebraic...
>
> Destroy?

It's too strict: you have to specify concrete types beforehand. 
This spills over into user code and makes it far less versatile 
that can be achieved.
Currently with allocators we have two extremes: IAllocator (and 
now, ISharedAllocator) that carries *no* static type information 
about concrete implementation, *and* loses all the inference 
regarding @nogc and shared memory. On the other end it's 
CAllocatorImpl that carries *both*.
But for user code, what is desirable is to have a middle man: a 
type that erases concrete allocator type but still keeps the 
@nogc and/or shared. This would enable user types to exchange 
their allocators while keeping static checks afforded by the 
language.
This can be done e.g. like this:

enum AllocatorTraits
{
     none            = 0x00,
     noGC            = 0x01,
     sharedMemory    = 0x02,
     sharedInstance  = 0x04,
}

mixin template AllocatorInterface()
{
     Ternary owns(Block block) @nogc;
     Ternary resolveInternalPointer(void* p, ref Block result) 
@nogc;
     Ternary empty() const @nogc;

     Block allocate(size_t, TypeInfo ti = null);
     Block alignedAllocate(size_t, uint);
     Block allocateAll();
     bool expand(ref Block, size_t);
     bool reallocate(ref Block, size_t);
     bool alignedReallocate(ref Block, size_t, uint);
     bool deallocate(Block block);
     bool deallocateAll();
}

template IAllocatorImpl(AllocatorTraits traits)
{
     static if (traits & AllocatorTraits.sharedInstance)
         alias Base = ISharedAllocator;
     else
         alias Base = IAllocator;

     interface IAllocatorImpl : Base
     {
         static if (traits & AllocatorTraits.sharedMemory)
             alias Block = shared(void)[];
         else
             alias Block = void[];

         static if (traits & (AllocatorTraits.sharedInstance | 
AllocatorTraits.noGC))
             @nogc shared { mixin AllocatorInterface!(); }
         else static if (traits & AllocatorTraits.sharedInstance)
             shared { mixin AllocatorInterface!(); }
         else
             @nogc { mixin AllocatorInterface!(); }

         mixin AllocatorInterface!();
     }
}

...and make the allocatorObject() function return 
IAllocatorImpl!traits instead of CAllocatorImpl!Allocator. With 
such IAllocatorImpl, user code can specify concrete expectations 
about the allocator without needing to know the exact allocator 
type.


More information about the Digitalmars-d mailing list