September 23, 2013
On 9/23/13 11:55 AM, Robert Schadek wrote:
> On 09/23/2013 07:16 PM, Andrei Alexandrescu wrote:
>> On 9/23/13 10:01 AM, deadalnix wrote:
>>
>>> Finally, we got to decide how these basics block are used to form typed
>>> allocators, and interact with language constructs.
>>
>> Sure. Again: I describe the Otto cycle and you discuss how to paint
>> the road.
> IMO there is a problem with this metaphor. If the road is painted
> metallic the Otto motor (cycle) needs cooling, otherwise ... boom. So I
> think the overall picture has to be kept in sight.
>

Which makes the metaphor unintentionally better. Yes, we do need to worry about higher concerns because that's how layerd abstractions work.

Andrei

September 23, 2013
On 9/23/13 11:59 AM, Jacob Carlborg wrote:
> On 2013-09-23 17:03, Andrei Alexandrescu wrote:
>
>> I'd think new already is translated into a library call. Walter?
>
> Yes, "new" is lowered to a couple different runtime functions. Here's a
> list:
>
> http://wiki.dlang.org/Runtime_Hooks

Thanks, this is great.

Currently "new" is fail because it calls functions passing TypeInfo objects, instead of calling type-parameterized functions. We must change that to have "new T(args)" lower into ".opNew!T(args)". Then object.d defines that function.


Andrei

September 23, 2013
On 09/23/2013 09:11 PM, Andrei Alexandrescu wrote:
> On 9/23/13 11:55 AM, Robert Schadek wrote:
>> On 09/23/2013 07:16 PM, Andrei Alexandrescu wrote:
>>> On 9/23/13 10:01 AM, deadalnix wrote:
>>>
>>>> Finally, we got to decide how these basics block are used to form
>>>> typed
>>>> allocators, and interact with language constructs.
>>>
>>> Sure. Again: I describe the Otto cycle and you discuss how to paint the road.
>> IMO there is a problem with this metaphor. If the road is painted metallic the Otto motor (cycle) needs cooling, otherwise ... boom. So I think the overall picture has to be kept in sight.
>>
>
> Which makes the metaphor unintentionally better. Yes, we do need to worry about higher concerns because that's how layerd abstractions work.
>
> Andrei
>
You're right! And I'm to tired to read properly.
September 23, 2013
On 9/23/2013 12:09 PM, Andrei Alexandrescu wrote:
> I think there's at least indirect support in e.g. generating typeinfo objects
> appropriately. Many of the components of those typeinfos are expressly defined
> for helping a tracing collector.

Those are not language features.

Also, the latest support for that is done with a library-defined template.

September 23, 2013
23-Sep-2013 22:52, Jacob Carlborg пишет:
> On 2013-09-23 17:47, Manu wrote:

>> Imagine if new was a template (it would have to be a template).
>> Allocating a template would require nested template syntax every time,
>> which is pretty ugly.
>>
>>    X x = new!(X!arg(args...)); // ewoo, paren spam...
>
> Why not:
>
> X x = new!X(args);
>

+1 Or call it make for the time being so as to not collide with the keyword.

-- 
Dmitry Olshansky
September 23, 2013
On 9/23/2013 9:47 AM, Benjamin Thaut wrote:
> I always understood void[] as block of unkown data.

Untyped data, not unknown data.

September 23, 2013
On 9/23/2013 10:08 AM, Andrei Alexandrescu wrote:
> I'm unclear on what void[] means starting from its semantics.

I agree that it should be void[], as that represents (in D) a block of untyped data. void[] should be ideal for a primitive allocator.

September 23, 2013
On 9/23/13 1:04 PM, Walter Bright wrote:
> On 9/23/2013 10:08 AM, Andrei Alexandrescu wrote:
>> I'm unclear on what void[] means starting from its semantics.
>
> I agree that it should be void[], as that represents (in D) a block of
> untyped data. void[] should be ideal for a primitive allocator.

Great, made that change, it all works. Does void[] make any promise about alignment?

Andrei

September 23, 2013
On 09/23/2013 01:49 AM, Andrei Alexandrescu wrote:
> I am making good progress on the design of std.allocator, and I am
> optimistic about the way it turns out. D's introspection capabilities
> really shine through, and in places the design does feel really
> archetypal - e.g. "this is the essence of a freelist allocator". It's a
> very good feeling. The overall inspiration comes from Berger's
> HeapLayers, but D's introspection takes that pattern to a whole new level.
> ...

Seems neat.

> Several details are still in flux, but at the top level it seems most
> natural to divide things in two tiers:
>
> 1. Typed allocator, i.e. every request for allocation comes with the
> exact type requested;
>
> 2. Untyped allocator - traffics exclusively in ubyte[].
> ...

Some general remarks:

One issue you will probably run into and maybe want to fix in some way during the typed allocator design is that private constructors cannot be called from templates parameterized on types.

E.g.:

module a;

auto New(T,Args...)(Args args){
    return new T(args);
}

// ---

module b;

class A{
    private this(){}
}

void main(){
    auto a = New!A(); // error
}

Is there an intention to also support replacements of instance new allocations, i.e. object.new subobject(args)?
September 23, 2013
On Sunday, 22 September 2013 at 23:49:56 UTC, Andrei Alexandrescu wrote:
> 1. Typed allocator, i.e. every request for allocation comes with the exact type requested;
>
> 2. Untyped allocator - traffics exclusively in ubyte[].

This is a good design.

Perhaps this is a later concern, but we should make sure that node-based containers (e.g. linked list, trees) have a way to access the allocation size needed for the node. STL did not do this.


> * alignment is a compile-time constant yielding the alignment of allocated data. Many allocators offer the maximum alignment of the platform (for which I used real.alignof above). This constant is required for all allocators.

What if, for example, I wanted to allocate a 4096 byte aligned block from the GC allocator? Do I have to create a new allocator backed by the GC allocator?

What if the alignment is not known at compile time (e.g. hard disk page size or CPU cache line size)?

Might be better to pass the desired alignment in the allocate method.


> * available is a property that returns how many total (not necessarily contiguous) bytes are available for allocation. The NullAllocator knows statically it has 0 bytes available so it implements it as an enum. Generally allocators will implement it as a @property. This property is optional.

It would be useful to know the maximum available contiguous block size too, so that you can find out if an allocation will succeed without calling allocate. It's also useful for diagnosing fragmentation issues e.g. "allocation failed, free memory = X, max contiguous = Y". If X is high and Y is low then you are highly fragmented.

Of course, this should be optional.


> * allocate(s) returns a ubyte[] with length at least s, or null. (It does not throw on out-of-memory because that would hurt composability; it turns out many elemental allocators do naturally run out of memory.) This method is required for all allocators. In most allocators this method should be @safe.

What are the semantics of allocate(0)? malloc(0) is implementation defined.