On Tuesday, 4 February 2014 at 23:51:35 UTC, Andrei Alexandrescu
wrote:
Consider we add a library slice type called RCSlice!T. It would have the same primitives as T[] but would use reference counting through and through. When the last reference count is gone, the buffer underlying the slice is freed. The underlying allocator will be the GC allocator.

Now, what if someone doesn't care about the whole RC thing and aims at convenience? There would be a method .toGC that just detaches the slice and disables the reference counter (e.g. by setting it to uint.max/2 or whatever).

Then people who want reference counting say

auto x = fun();

and those who don't care say:

auto x = fun().toGC();


Destroy.

Andrei

I think I'd rather have a higher-level solution than this. I
would worry about having to reason about code that's littered
with toGC() or toARC() calls: my peanut butter (application
logic) is now mixed in with my chocolate (allocation logic),
making both harder to understand.

I thought there was some discussion about arenas and custom
allocators a while back, and that seemed like a sensible way to
address these issues. I had imagined (naively?) that I would have
been able to write something like:

auto someFunction(T)(T params)
{
   ComplicatedResult result;
   {
     // set up allocator at start of scope
     auto arena = GrowableArena();
     push_allocator(arena); // thread-local allocator
     scope(exit) pop_allocator();

     // call as many expensive functions as you like...
     auto tmp = allocation_intensive_computation(params);

     // transitive-move result from arena, at the scope's tail
     result = tmp.toGC();
   } // arena goes out of scope and is deallocated

   return result;
}

So, allocation and lifetime issues are handled at the boundaries
of scopes that have custom allocators associated with them.

Um... destroy?

Graham

Reply via email to