More radical ideas about gc and reference counting

Michel Fortin via Digitalmars-d digitalmars-d at puremagic.com
Sun May 4 05:16:51 PDT 2014


On 2014-05-04 09:00:45 +0000, "Marc Schütz" <schuetzm at gmx.net> said:

> On Saturday, 3 May 2014 at 11:12:56 UTC, Michel Fortin wrote:
>> Or turn the rule on its head: make it so having a destructor makes the 
>> heap memory block reference counted. With this adding a destructor 
>> always cause deterministic destruction.
>> 
>> The compiler knows statically whether a struct has a destructor. For a 
>> class you need a runtime trick because the root object which can be 
>> either. Use a virtual call or a magic value in the reference count 
>> field to handle the reference count management. You also need a way to 
>> tag a class to be guarantied it has no derived class with a destructor 
>> (to provide a static proof for the compiler it can omit ARC code), 
>> perhaps @disable ~this().
>> 
>> Then remains the problem of cycles. It could be a hard error if the 
>> destructor is @safe (error thrown when the GC collects it). The 
>> destructor could be allowed to run (in any thread) if the destructor is 
>> @system or @trusted.
>> 
>> The interesting thing with this is that the current D semantics are 
>> preserved, destructors become deterministic (except in the presence of 
>> cycles, which the GC will detect for you), and if you're manipulating 
>> pointers to pure memory (memory blocks having no destructor) there's no 
>> ARC overhead. And finally, no new pointer attributes; Walter will like 
>> this last one.
> 
> This is certainly also an interesting idea, but I suspect it is bound 
> to fail, simply because it involves ARC. Reference counting always 
> makes things so much more complicated... See for example the cycles 
> problem you mentioned: If you need a GC for that, you cannot guarantee 
> that the objects will be collected, which was the reason to introduce 
> ARC in the first place. Then there are the problems with shared vs. 
> thread-local RC (including casting between the two), and arrays/slices 
> of RC objects. And, of course, Walter doesn't like it ;-)

Arrays/slices of RC objects would have to be reference counted too. 
That was part of Andrei's proposal.

Cycles break deterministic destruction and break the guaranty the 
destructor will be called because we're relying on the GC to free them, 
true. But today we have no guaranty at all, even when there's no cycle. 
It is possible to avoid cycles, and not that hard to do in a safe way 
when you have weak (auto-nulling) pointers (which D should have 
regardless of the memory management scheme). It's even easier if you 
use the GC to detect them. I'm proposing that GC calls to a @safe 
destructor be a hard error so you can use that error to fix your 
cycles. (Note that cycles with no destructor are perfectly fine though.)

As for shared vs. thread-local RC, Andrei proposed a solution for that earlier.
http://forum.dlang.org/post/ljrr8l$2dt1$1@digitalmars.com

I know Walter doesn't like to have pointers variables do magic stuff. 
This is why I'm confining ARC behaviour to objects, structs, and arrays 
having destructors. Andrei's initial proposal was to completely remove 
destructors for objects; all the pointers that would have survived that 
proposal are still RC-free in mine except for non-final classes when 
you haven't explicitly disabled the destructor. (An alternative to 
disabling the destructor would be to use a different root object for 
RC, I just find that less desirable.)

Frankly, if we want destructors to work safely when on the heap, I 
don't see another way.

-- 
Michel Fortin
michel.fortin at michelf.ca
http://michelf.ca



More information about the Digitalmars-d mailing list