Orphan ranges

Steven Schveighoffer schveiguy at yahoo.com
Mon Apr 16 04:37:56 PDT 2012


On Sun, 15 Apr 2012 12:34:11 -0400, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> I'm making good progress on an allocator design. If things come together  
> as I hope, it'll kick some serious ass.
>
> I'm currently looking at four allocation models:
>
> * straight GC, safe (no deallocation)
> * GC + the ability to free memory
> * malloc/free, unsafe, buyer beware (STL-level safety)
> * reference counted (based on either malloc or GC+free)
> * region (scoped)

* pool/freelist based.  Dcollections has such an allocator (Called a chunk  
allocator), which I hope would be applicable.  It's in fact the default  
allocator.

I saw you responded later that it will be a generic parameter.  While I  
support that, and it is the same model in dcollections, it leaves a lot to  
be desired.  For instance, if I have a RedBlackTree of SList!int, will  
each SList have it's own copy of an allocator?  Sure you could use a  
singleton allocator to avoid overhead, but what if I simply want only the  
SLists in my RedBlackTree to share an allocator, and not with all  
SList!int?

I've been occasionally putting some thought into that for dcollections,  
and I haven't really come up with a good solution yet, but it feels  
withink reach with some dedicated effort.  I'm interested if you have a  
solution for this in mind.

> I need to kink out a few details, most important being - is safety part  
> of the allocator or an extricable property that's a different policy?  
> For now I have a related question about orphan ranges.

It's definitely an allocator property.  For example, malloc/free is  
unsafe, there is no way to make it safe.

> Consider this motivating example:
>
> void main()
> {
>      int[] x;
>      {
>          auto b = new int[20];
>          x = b[5 .. $ - 5];
>      }
>      ... use x ...
> }
>
> The range x is a 10-elements range that originates in a 20-element  
> array. There is no safe way to access the original array again, so in a  
> sense the other 10 elements are "lost". That's why I call x an orphan  
> range - a range of which original container is gone.
>
> Built-in arrays work routinely like that, and in fact the originating  
> arrays are not distinguished by type in any way from their ranges (be  
> they orphan or not). The question is, what should std.container do about  
> orphan ranges in general? Should it allow them, disallow them, or leave  
> the decision open (e.g. to be made by the allocator)? Depending on what  
> way we go, the low-level design would be quite different.

I'd like to slightly correct your statement ;)  b is a 20-element range  
that originates in a 31-element array (b.capacity is 31).  The GC is the  
allocator and owner of the array type, which has no formal type.

But I understand the question.  and I think the situation is somewhat  
different -- most ranges will not be able to be attached spontaneously to  
different container instances.  Nor will they rely on the allocator to  
generate extra instances at will to appease the requests.  Built-in  
arrays/slices are like that.

However, I think absolutely we need orphan range support.  I think it's  
really a property of the allocator, not the container, as to whether  
orphan ranges exist.  For proof, look no further than your list of  
possible allocators at the malloc/free version.  Clearly orphan ranges are  
not implementable using that back-end, since once you lose your original  
container reference, the memory is leaked.

If we make it container policy, any container would have to disallow that  
allocator.  I think that's too restrictive, and makes the malloc/free  
allocator somewhat useless.

In terms of "allowance", I don't see how you disallow them.  All I think  
you can do is make using orphaned ranges defined behavior or not.

-Steve


More information about the Digitalmars-d mailing list