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.