draft proposal for ref counting in D

Walter Bright newshound2 at digitalmars.com
Wed Oct 9 18:50:16 PDT 2013


Michel Fortin wrote:

Le 27-juin-2013 à 13:04, Walter Bright  a écrit :

 > I don't think we should do a fully ref counted GC anyway.

Speaking of the GC, you should probably rethink this point:

 > 14. RC objects will still be allocated on the GC heap - this means that a normal
 > GC run will reap RC objects that are in a cycle, and RC objects will get 
automatically
 > scanned for heap references with no additional action required by the user.

If you allocate the object from the GC heap, the GC will collect it regardless 
of its reference count. That's fine as long as all the retaining pointers are 
visible to the GC. But if you're defining a COM object, likely that's because 
you'll pass a pointer to an external API, and this API might store the pointer 
somewhere not scanned by the GC. This API will call AddRef to make sure the 
object is retained, but if the GC doesn't see that pointer on its heap it'll 
deallocate and next time external code uses the object everything goes boom! So 
that doesn't work.

If instead you allocate the object outside of the GC heap and your object 
contains pointers to the GC heap, you'll need to add roots to the GC for any 
pointer variable in the object. (This is what DMD/Objective-C currently does.) 
There's no way to detect cycles with that scheme, but it is simple.

We could use a hybrid scheme with two reference counts: one for internal 
references that the GC can see and one for external references that the GC 
cannot see. The GC cannot collect an object if the external reference count is 
non-zero. If the external count is zero, it can collect the object if the 
internal reference count reaches zero or if it becomes unreachable from any 
root. This allows detection of cycles, as long as this cycle is only made of 
internal references. Care must be taken about incrementing/decrementing the 
right reference count depending on the context, which sounds tricky.

Or we could use a somewhat less hybrid scheme where we have one reference count 
and the only thing it does is prevent objects from being deallocated. This can 
be implemented as one global hash table and you put all objects that have a 
non-zero reference count in that table. This hash table being scanned by the GC 
anything in it will never be collected. This will also detect internal cycles 
like the previous two-counter scheme, but it doesn't allow immediate 
deallocation as it waits for the GC to deallocate. (This is similar to how it 
worked in my defunct D/Objective-C bridge that did not rely on tweaking the 
compiler.)



More information about the Digitalmars-d mailing list