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.

Reply via email to