September 24, 2013 Re: std.allocator needs your help | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | 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 |
September 24, 2013 Re: std.allocator needs your help | ||||
---|---|---|---|---|
| ||||
Posted in reply to Namespace | On 9/24/13 3:11 PM, Namespace wrote:
>> I would rather want new to be overloadable and have 2 sets of parameters
>>
>> new (allocator)(arg1, arg2)
>>
>> Where "allocator" would go to the overloaded version of new and "arg1"
>> and "arg2" will be passed to the constructor.
>
> +1
We're banning that syntax of new.
Andrei
|
September 25, 2013 Re: std.allocator needs your help | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Tuesday, 24 September 2013 at 15:57:00 UTC, Andrei Alexandrescu wrote: > Also, I hope we'll be able to allow allocators to define Pointer(T), Ref(T) etc. that supplant replacements for the built-in notions of pointer, reference etc. Then, user code that uses these notions instead of the built-in ones will be guaranteed some nice properties (e.g. automatic reference counting). Unfortunately I don't see a way for an allocator to enforce that its users don't do illegal things such as escaping addresses etc. So it would be a discipline-backed scheme. Notable beneficiaries will be containers. > It will be fun without tail const. > 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. > It doesn't make any sens at this level. These allocator do not know what a pointer is. And can't be @safe if they do know. |
September 25, 2013 Re: std.allocator needs your help | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Tuesday, 24 September 2013 at 19:27:13 UTC, Andrei Alexandrescu wrote:
> Second, there's no need for a defaulted argument; the aligned allocation can be an optional overload of the one-argument function. I'm looking into ways to compose with that overload.
>
This or something like
allocator.setAlignement(...);
allocator.allocate(...);
|
September 25, 2013 Re: std.allocator needs your help | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Andrei Alexandrescu:
> Also, I hope we'll be able to allow allocators to define Pointer(T), Ref(T) etc. that supplant replacements for the built-in notions of pointer, reference etc. Then, user code that uses these notions instead of the built-in ones will be guaranteed some nice properties (e.g. automatic reference counting). Unfortunately I don't see a way for an allocator to enforce that its users don't do illegal things such as escaping addresses etc. So it would be a discipline-backed scheme. Notable beneficiaries will be containers.
Adding some compiler help is not forbidden. (Also for reference counting).
Bye,
bearophile
|
September 25, 2013 Re: std.allocator needs your help | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Tuesday, 24 September 2013 at 22:39:27 UTC, Andrei Alexandrescu wrote:
> On 9/24/13 3:11 PM, Namespace wrote:
>>> I would rather want new to be overloadable and have 2 sets of parameters
>>>
>>> new (allocator)(arg1, arg2)
>>>
>>> Where "allocator" would go to the overloaded version of new and "arg1"
>>> and "arg2" will be passed to the constructor.
>>
>> +1
>
> We're banning that syntax of new.
>
It seem to me like typed allocator should try to fit in rather than redefine everything.
|
September 25, 2013 Re: std.allocator needs your help | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bigsandwich | On Tuesday, 24 September 2013 at 18:53:56 UTC, Bigsandwich wrote:
> Hi,
>
> I mostly just lurk around here, but occasionally I just can't resist putting in my two cents. I really want to see D replace C++ for AAA games (my industry) and allocators are really critical to that. I think there's an elephant here that most of the posts have been dancing around.
>
> In C++ when you roll your own allocators (whether STL allocators or some other interface) there is basically, only one set of *semantics* to worry about - the classic C++/C pattern of new/delete or malloc/free. This is actually much more complicated in D where you have at least two different semantics:
>
> 1) C++/C style
> 2) Tracing/Garbage Collection
> 3) Region allocators and other oddballs
>
> Consequences:
> 1) These semantics aren't really interchangeable. If, for instance, a library is implemented with one of them in mind, it can only be replaced by an allocator with the same semantics.
>
> 2) Tracing/Garbage Collection are required for whatever the default allocator is and replacement allocator must implement those semantics.
>
> 3) Its only possible to change (2) by hacking the runtime so that any language features that rely on the GC cause errors.
>
> The design Andrei has presents seems to *allow* the creation of allocators with all of these semantics, but it doesn't seem to answer the following questions:
>
> 1) Can semantics be enforced?
> 2) Can allocators with different semantics be composed?
> 3) Can different semantics for the default allocator be implemented?
> 4) If so, how can I reconcile that with libraries that expect different default semantics? A use case that I foresee for something like this would be banning the use of GC in low level engine code, but allowing it in higher level gameplay code.
>
> 5) Are any of these questions even relevant for this part of the design or will we have to wait for the rest of it to know the answers?
>
> Thanks.
I'd like to see these question answered. This is one of the most insightful posts of the discussion.
|
September 25, 2013 Re: std.allocator needs your help | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | On 9/24/13 6:42 PM, deadalnix wrote:
> On Tuesday, 24 September 2013 at 22:39:27 UTC, Andrei Alexandrescu wrote:
>> On 9/24/13 3:11 PM, Namespace wrote:
>>>> I would rather want new to be overloadable and have 2 sets of
>>>> parameters
>>>>
>>>> new (allocator)(arg1, arg2)
>>>>
>>>> Where "allocator" would go to the overloaded version of new and "arg1"
>>>> and "arg2" will be passed to the constructor.
>>>
>>> +1
>>
>> We're banning that syntax of new.
>>
>
> It seem to me like typed allocator should try to fit in rather than
> redefine everything.
The banning is orthogonal to allocators.
Andrei
|
September 25, 2013 Re: std.allocator needs your help | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On Tuesday, 24 September 2013 at 22:39:27 UTC, Andrei Alexandrescu wrote:
> On 9/24/13 3:11 PM, Namespace wrote:
>>> I would rather want new to be overloadable and have 2 sets of parameters
>>>
>>> new (allocator)(arg1, arg2)
>>>
>>> Where "allocator" would go to the overloaded version of new and "arg1"
>>> and "arg2" will be passed to the constructor.
>>
>> +1
>
> We're banning that syntax of new.
>
> Andrei
What's wrong with this syntax?
And: *That* syntax or complete 'new' as built-in feature?
|
September 25, 2013 Re: std.allocator needs your help | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | Am 25.09.2013 00:39, schrieb Andrei Alexandrescu: > On 9/24/13 3:11 PM, Namespace wrote: >>> I would rather want new to be overloadable and have 2 sets of parameters >>> >>> new (allocator)(arg1, arg2) >>> >>> Where "allocator" would go to the overloaded version of new and "arg1" >>> and "arg2" will be passed to the constructor. >> >> +1 > > We're banning that syntax of new. > > Andrei I always love it when people just plain ignore all the arguments I made ... -- Kind Regards Benjamin Thaut |
Copyright © 1999-2021 by the D Language Foundation