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