std.allocator needs your help

Dmitry Olshansky dmitry.olsh at gmail.com
Tue Sep 24 15:35:00 PDT 2013


25-Sep-2013 00:39, Andrei Alexandrescu пишет:
> On 9/24/13 1:02 PM, Dmitry Olshansky wrote:
>> 24-Sep-2013 19:56, Andrei Alexandrescu пишет:
>>> It could, but as I mentioned to Manu - at this level any cost is
>>> significant. Even changing from a compile-time constant to a global
>>> static dynamically-initialized constant has a cost. Making alignment an
>>> instance variable turns stateless allocators into stateful ones.
>>
>> Hm most could just get away with an enum. Am I missing something?
>
> Right now I do things like:
>
> struct DopeAllocator(Allocator, Dope)
> {
>      static assert(Allocator.alignment >= Dope.alignof,
>          "DopeAllocator does not work with allocators offering a smaller"
>          " alignment than the dope alignment.");
>      static assert(!hasElaborateDestructor!Dope,
>          "DopeAllocator: ellaborate destructors for Dope not
> implemented.");
>
>      enum alignment = Dope.alignof;
>
>      ...
> }
>
But it's a boiler plate regardless.
What if we are to provide the tools to manipulate said alignment 
composition (some imaginary templates in action):

alias alignment = requireAlignment!(Allocator, 
Dope.alignof).overrideAlignment!(Dope.alignof);

Which in this case would unfold to a proper primitive that tests 
alignment of Allocator at RT or CT, and then return fixed value as new 
alignment.

> Such code would be significantly more involved if Allocator had the
> freedom to define alignment as either an enum, a static method, or a
> member function.

Well you solved static vs member function issue already (via singleton).

>>> I'm hoping to get away with a static function "static uint alignment()"
>>> that (a) is CTFEable for most allocators/platforms, (b) uses a
>>> dynamically-initialized static constant for a few. Then derived
>>> allocators will inherit CTFEability.
>>
>> A check for CTFE-ablity might do the trick. The run-time dependent ones
>> usually would immediately hit a wall that is a sys-call or WinAPI.
>
> It does. It's just some more work. Guess I'd need to put it in.
>
>>> Would a per-allocator-type alignment suffice?
>>
>> I see alignment as an inherent property of the way an allocator acquires
>> memory.
>
> The question remains, is it a property of the allocator _object_ or a
> property of the allocator _type_? I.e. do we need to support allocators
> that store alignment as a nonstatic member variable?
>
>> Sad but true one can't determine the actual alignment of some
>> important ones at CTFE. Even worse adapters would in turn depend on
>> these system-specific run-time values such as half a page, 2 cache lines
>> etc.
>>
>> auto my2PageAligner = AligningAllocator(page_size*2, rootAllocator)
>>
>> where page_size is calculated elsewhere.
>
> That can be made to work, it's just that page_size would be a static
> variable that the user must set (not a template argument).

Right. So another angle to the problem is that maybe we could just 
provide a set of run-time "base" values for alignment. Then one can use 
say x-page alignment defining x at compile-time.

The only problem I foresee with this is that: std.allocator is ill 
suited to determine all base alignments it may need.
Say a certain kind of disk sector size (some 3rd party code), or DMA 
block size (or what it's called) on some system. Maybe it's that 1% that 
is not worth it but I dunno.

>> expand should do the trick. I think that nicely saves on primitives
>> count. But we may have to add a 'shrink' if you are so bent on never
>> decreasing size in expand :)
>> And ... reallocate doesn't cut it as long as there is no big red tape on
>> it that says - if decreasing the size reallocation it is ALWAYS in-place
>> (it might not be true for some allocators - e.g. realloc doesn't
>> guarantee even this IIRC).
>
> OK, I'm willing to add the optional method shrink(void[], size_t
> newSize) if expand() and realloc() are insufficient.

Okay let it be shrink. If the @safety of expand is that important and 
the fact it may make no sense to shrink on a call to expand. Honestly I 
could see a lot of code doing things like

if(newSize < oldSize) shrink(...)
else if(newSize > oldSize) expand(...)

Maybe it's fine.

> Indeed realloc()
> does not guarantee immovability, and we also shouldn't because
> Mallocator must be compatible the C API.

Spawn of Satan :)

-- 
Dmitry Olshansky


More information about the Digitalmars-d mailing list