More radical ideas about gc and reference counting

Manu via Digitalmars-d digitalmars-d at puremagic.com
Mon May 5 19:52:43 PDT 2014


On 4 May 2014 19:00, via Digitalmars-d <digitalmars-d at puremagic.com> wrote:
> On Saturday, 3 May 2014 at 11:12:56 UTC, Michel Fortin wrote:
>>
>> On 2014-05-01 17:35:36 +0000, "Marc Schütz" <schuetzm at gmx.net> said:
>>
>>> Maybe the language should have some way to distinguish between GC-managed
>>> and manually-managed objects, preferably in the type system. Then it could
>>> be statically checked whether an object is supposed to be GC-managed, and
>>> consequentially shouldn't have a destructor.
>>
>>
>> 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.

So specify that improper weak reference attribution may lead to
interference with proper execution of destructors. People generally
understand this, and at least they'd have such a tool to make their
code behave correctly.
Perhaps even have rules that things with destructors create static
errors if they are used in a way that may create circular references
when effective weak attribution is not detected by the compiler (if
such a thing is statically possible?).

> Then there are the problems with shared vs. thread-local RC (including
> casting between the two),

The problem is exactly the same as 'shared' exists already. What makes
it any different?
shared <-> not-shared requires blunt casting, and the same can apply
to shared RC. 'shared' implies RC access must use atomics, and
otherwise not, I don't imagine any distinction in data structure?

> and arrays/slices of RC objects.

Slices need to know their offset (or base pointer), or have an
explicit RC pointer. Either way, I don't see how slices are a
particularly troublesome case.
12byte slices on x32 - needs an extra field, 16 bytes should still be
sufficient on x64 considering that 64bit pointers are only 40-48 bits,
which means there are loads of spare bits in the pointer and in the
slice length field; should be plenty to stash an offset.

> And, of course,
> Walter doesn't like it ;-)

True. But I'm still waiting to see another even theoretically workable solution.



More information about the Digitalmars-d mailing list