When I initially created my allocators proposal, I figured wrongly that
the community would be most interested in seeing a few examples of
allocators and that a more formal specification of the allocator
interface wasn't terribly important yet. I was wrong, so I got off my
butt and wrote a more formal specification. I also made a few other
important changes to my allocators proposal:
1. DynamicAllocator allows a struct or class that conforms to the
structural allocator interface to be turned into a runtime interface
with virtual functions, etc. The reason for this trick instead of just
making Allocator a "virtual" interface is to allow scoped allocators,
allocators with value semantics, allocators with reference counting,
etc. and only live within the constraints of the virtual function world
when absolutely necessary. One examples of where the virtual function
world is a severe constraint is the templated functions create,
newArray, uninitializedArray and array. These were simply left out of
the DynamicAllocator. Another is the ugliness and unsafety of using the
DynamicAllocator interface with RegionAllocator, as RegionAllocator's
scoped semantics create a severe impedance mismatch.
2. I added create(T) for creating new class and struct instances on an
allocator.
3. I cleaned up the documentation of RegionAllocator according to
Andrei's suggestions. I double-checked and freeIsChecked, etc. are
enums. DDoc just doesn't reflect this.
4. Various fixes for small bugs pointed out by the community.
5. Noted that finalizers/destructors are never automatically called
when RegionAllocator-allocated memory gets freed, because the
bookkeeping burden of this would be unacceptable and it would prevent
O(1) freeing. RegionAllocator is such an unsafe performance hack anyhow
that I see very little wrong with "buyer beware" here. Besides, most
use cases for it (at least most of mine) are allocating temporary arrays
of primitives and containers would use the lower-level DynamicAllocator
interface. YMMV.
6. I did **not** change the documentation of the relationship between
RegionAllocatorStack and RegionAllocator because I just don't see a good
way to do it. I'm open to suggestions.
7. std.regionallocator -> std.allocators.region, etc.
8. The high-level, templated allocator functions now have a default
implementation in terms of lower-level allocator functionality, provided
by the TypedAllocatorMixin mixin in std.allocators.allocator. The idea
is that an allocator may have better ways of accomplishing this stuff,
but this mixin is usually a reasonable default and will avoid code
duplication across allocators. I'm leery of including it in the
DynamicAllocator interface, though, because for some allocators it's
just plain wrong. For example, the default array() implementation just
plain wouldn't work with RegionAllocator for huge ranges.
Code:
https://github.com/dsimcha/TempAlloc/tree/master/std/allocators
Docs:
http://cis.jhu.edu/~dsimcha/d/phobos/std_allocators_allocator.html
http://cis.jhu.edu/~dsimcha/d/phobos/std_allocators_gc.html
http://cis.jhu.edu/~dsimcha/d/phobos/std_allocators_region.html