On 9/10/11 4:37 PM, dsimcha wrote:
I mostly took your proposal from a few months ago and doctored it
slightly. Basically, my theory was to define the allocator interface by
example (both RegionAllocator and GCAllocator being examples) and
resolve any ambiguities through the review process before creating more
formal documentation of the allocator interface. I'll probably create a
std.allocator.allocator, which would be similar to the top of
std.container and contain documentation of the general allocator interface.
Then I think we all need to defer reviews to that time.
Containers will need an allocator, and I think it's best to make it a
straight dynamic interface. In that design, the region allocator would
offer the scoped structs PLUS factory methods in those structs that
return implementations for those interfaces.
"Dynamic" as in using the `interface` keyword?
Yes.
My concern with this is
that a major purpose of RegionAllocator is to avoid the GC and its
global lock like the plague. I think it would be a **terrible** misuse
of things if you had to perform a heap allocation to get at the dynamic
interface. I'll think about this, though. There may be an easy workaround.
A possibility is to allocate the interface's implementation not with
new, but instead straight in your own allocator.
Containers will need to use an interface-based allocator. It's not a
lightly-taken decision, but it's the least of many evils. If we can't
get a scoped allocator to give back interfaces, we won't be able to use
containers with scoped allocators.
My other concern is that dynamic interfaces would break ref counting of
RegionAllocator instances because the GC frees things in an undefined
order, and I guess you'd have to rely on the GC to free a region. Maybe
I'm completely misunderstanding your suggestion, though.
The types as you define them stay put. All we need is a method
getAllocatorInterface() that returns an interface. It would be simplest
to allocate that interface's implementation on the heap because it makes
things safe. But then safety is not this allocator's stronghold.
* It's region_allocator or region.allocator, not regionallocator.
Ironically a good example of why is in this very name - is it "region
allocator" or "regional locator"?
You mean for the module name? I was thinking std.allocators.region. Are
you ok with this, too?
Yah, I just emphasized the convention.
* Enumerated paragraphs are not visually distinguished.
If you mean the lists of advantages/disadvantages at the top of the
module, I'd like to distinguish them better but don't know how to in
DDoc. Any advice?
$(OL ...)
* I didn't understand from the dox what the relationship between
RegionAllocator and RegionAllocatorStack is, mainly because
RegionAllocator is used before having been defined. (This is a difficult
problem in general.)
Hmm, maybe I should move RegionAllocator before RegionAllocatorStack and
focus on the thread-local default instantiation first, since this is
what people should use for most simple use cases. Creating explicit
RegionAllocatorStack instances is a more advanced use case.
I see two possibilities among many others:
1. Motivate properly both, then introduce them in their logical order.
2. Motivate one in ways independent from the other, introduce it,
motivate the second by distinguishing from the first, introduce it.
See what fits this case best.
* The GCScan enum is defined uncomfortably far from the places where
it's relevant. (Another difficult matter.)
I agree, but I don't really see any easy way to fix this. I could put
GCScan inside RegionAllocatorStack, but who wants to type
RegionAllocatorStack.GCScan.yes just to get a simple flag?
Cue that long discussion about yesno, named parameters etc. :o)
* In fact new(Uninitialized)Array should not be a member as its workings
are not specific to this allocator. It should be a free function taking
an allocator as a parameter.
My concern about this is that some allocators might want to do some
"special" things based on knowing the type. A good example is that
GCAllocator decides whether to scan for pointers based on knowing the
type. RegionAllocator has a completely different method for determining
this policy. When/if I make a std.allocators.allocator (which would
contain documentation of the general allocator interface, etc.) I can
make a mixin template that provides default implementations of things
that have obvious implementations in terms of lower-level allocator
features. (I think array() would also be included here.) This could be
mixed in and overridden if need be, but would provide the defaults to
save on code duplication across allocators.
All good points, which suggest that, again, we need some more design,
code, and review time for the region allocator. I don't think we should
approve region allocator as a tentative implementation of an interface
that hasn't been decided yet.
Generally it would be great to avoid type parameterization of the
allocator. It's been in the STL since forever and it hasn't anything
good. But you're making a good point about scanning. It would be perfect
if generally the GC knew for most or all pieces of memory their type.
Andrei