draft proposal for ref counting in D

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


On 6/27/2013 11:38 AM, 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.

We already require that if you're going to pass a pointer to any GC allocated 
data to external code, that you retain a pointer. I see no additional issue with 
requiring this for COM objects created on the GC heap.

 >
 > 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.

Yes, but that's a lot harder (and more error-prone) than simply requiring the 
programmer to retain a pointer as I outlined above.

 >
 > 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.

That also seems far more complex than what I proposed.

 >
 > 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.)
 >

I'd really like to stick to the shared_ptr<T> model. (A global hash table also 
is not so simple when factoring in loading and unloading DLLs.) Of course, for 
the O-C bridge, you can implement it as required to be compatible with O-C.



More information about the Digitalmars-d mailing list