std.allocator needs your help

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Tue Sep 24 13:39:05 PDT 2013


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;

     ...
}

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.

(Background: DopeAllocator!(A, D) allocates an object of type D just 
before every allocation and offers user code access to it. Allocations 
are made using A.)

>> 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).

>> The global GC does offer manual deallocation. It's the presence of
>> collect() that indicates tracing abilities. If deallocateAll() is
>> present, user code must assume it will be called during destruction.
>>
>
> I was looking into how some library would have to tweak its code based
> on presence/absence of some methods. For instance if there is collect,
> it doesn't have to call deallocate (even if present). If not then it has
> to call deallocate (again if present). Ditto with deallocateAll  with or
> without explicit deallocate.

Yah, my std.allocator prototype has a bunch of such logic.

> 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. Indeed realloc() 
does not guarantee immovability, and we also shouldn't because 
Mallocator must be compatible the C API.



Andrei


More information about the Digitalmars-d mailing list