On Wed, Jun 26, 2013 at 04:31:40PM +0200, cybervadim wrote: > On Wednesday, 26 June 2013 at 14:26:03 UTC, H. S. Teoh wrote: > >Yeah, I think the best approach would be one that doesn't require > >changing a whole mass of code to support. Also, one that doesn't > >require language changes would be far more likely to be accepted, as > >the core D devs are leery of adding yet more complications to the > >language. > > > >That's why I proposed that gc_alloc and gc_free be made into > >thread-global function pointers, that can be swapped with a custom > >allocator's version. This doesn't have to be visible to user code; it > >can just be an implementation detail in std.allocator, for example. > >It allows us to implement custom allocators across a block of code > >that doesn't know (and doesn't need to know) what allocator will be > >used. > > > > Yes, being able to change gc_alloc, gc_free would do the work. If > runtime remembers the stack of gc_alloc/gc_free functions like pushd, > popd, that would simplify its usage. I think this is a very nice and > simple solution to the problem.
Adam's idea does this: tie each replacement of gc_alloc/gc_free to some stack-based object, that automatically cleans up in the dtor. So something along these lines: struct CustomAlloc(A) { void* function(size_t size) old_alloc; void function(void* ptr) old_free; this(A alloc) { old_alloc = gc_alloc; old_free = gc_free; gc_alloc = &A.alloc; gc_free = &A.free; } ~this() { gc_alloc = old_alloc; gc_free = old_free; // Cleans up, e.g., region allocator deletes the // region A.cleanup(); } } class C {} void main() { auto c = new C(); // allocates using default allocator (GC) { CustomAlloc!MyAllocator _; // Everything from here on until end of block // uses MyAllocator auto d = new C(); // allocates using MyAllocator { CustomAlloc!AnotherAllocator _; auto e = new C(); // allocates using AnotherAllocator // End of scope: auto cleanup, gc_alloc and // gc_free reverts back to MyAllocator } auto f = new C(); // allocates using MyAllocator // End of scope: auto cleanup, gc_alloc and // gc_free reverts back to default values } auto g = new C(); // allocates using default allocator } So you effectively have an allocator stack, and user code never has to directly manipulate gc_alloc/gc_free (which would be dangerous). T -- Almost all proofs have bugs, but almost all theorems are true. -- Paul Pedersen