Phobos 3 Discussion Notes - 02-01-2024

Paul Backus snarwin at gmail.com
Wed Feb 7 16:20:31 UTC 2024


On Wednesday, 7 February 2024 at 10:10:27 UTC, Atila Neves wrote:
> On Wednesday, 7 February 2024 at 05:55:04 UTC, Paul Backus 
> wrote:
>> In my proposal, when you use a library container (like an 
>> array, a hash table, a binary tree, etc.), you can specify 
>> what type of allocator you want to use as a template parameter 
>> (as in, `Array!(int, GC)`). It will probably default to the 
>> GC, but you can just as easily use malloc, or even a custom 
>> allocator that you write yourself.
>
> The problem with this approach, as C++ found out, is that 
> `Vector!(int, MyAlloc)` is a different type from `Vector!(int, 
> YourAlloc)`. The way I got around that is by defaulting to a 
> global allocator. This has its drawbacks as well of course, 
> because now everything is a virtual call.

Yes, I'm aware of this problem, but I don't see a way around it.

The thing is, the compiler has to know what allocator you're 
using at compile time in order to infer the correct function 
attributes for the container. If you want `Array!int` to default 
to using the GC, but also work in `@nogc` code when you're using 
`malloc`...how would that even work?

I have two potential mitigations for this problem in mind.

The first is to realize that D already has a solution for writing 
data-structure-agnostic code: ranges! If `Array` implements all 
of the relevant range interfaces, the rest of your code doesn't 
have to depend on any single concrete `Array` type--it can just 
depend on the range interface.

If you really need a concrete type, there's always 
`std.range.interfaces`, although that does come with some 
sacrifices (virtual calls, not `@safe` or `@nogc`, etc.).

The second is to have the allocator library provide a 
runtime-polymorphic allocator, which users can depend on if they 
absolutely need a single concrete container type for whatever 
reason. We'd have to make some serious tradeoffs between runtime 
overhead and attribute compatibility, and it's possible that no 
one-size-fits-all solution exists, but in principle, it can be 
done.

Finally, on the subject of global allocators: I don't think 
having a global allocator is a good idea, period, whether it's 
used as a default or not. Containers generally cannot tolerate 
having their allocators mutated "behind their backs," and a 
user-accessible global variable would make it very easy and 
tempting to write code that does this.


More information about the Digitalmars-d mailing list