D2 weak references

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Wed Apr 22 14:39:01 PDT 2009


Jason House wrote:
> Frits van Bommel Wrote:
> 
>> Leandro Lucarella wrote:
>>> I think instead of a notification mechanism access to the mark bit can be
>>> provided.
>>>
>>> The mark phase is ran with all thread paused, so you don't need any
>>> notifications in that phase because nobody can ask the weak ref object for
>>> the underlaying pointer then.
>>>
>>> When threads are resumed, the mark phase is complete, so the invariant of
>>> all live objects having the mark bit set and all the garbage having the
>>> bit unset should hold. If the GC guarantee that the mark bit is set
>>> *always* when a object is live (the mark bit clearing should be done with
>>> all threads stopped and that should be it), except only when the mark
>>> phase is running, then, a weak ref implementation can look at the mark bit
>>> to safely see if the reference is garbage or not (even before the sweep
>>> phase find it and call the finalizer).
>>>
>>> I think this approach is both simple and efficient, it doesn't have races
>>> at all (unless I'm missing something, of course). The only problem is it's
>>> too tied to the current GC implementation. But I think any weak ref
>>> implementation will, so it looks like weak ref really belong to the GC.
>> I think you're missing something. Consider this sequence of events:
>> - Object A is collected by the GC. (And its mark bit M is cleared)
>> - Object B is allocated, and gets the memory formerly used by object A. Mark bit 
>> M is set.
>> - A weak reference to A gets used; it checks mark bit M, which is set...
>>
>> In other words, the "this object was collected" state needs to be stored in the 
>> weak reference, not in the object that got collected (or anything tied to its 
>> memory location) because that memory may get reused.
> 
> That's where finalizers come in. They can mark the weak ref as invalid so that you don't care what was returned. In my (recent?) pseudo code, the weak ref was decoded, the mark bit was checked, and then the weak ref was decoded again. The final decoding is to solve the race with the finalizer.

Will this work if B was allocated in another thread, right after it gets resumed 
(i.e. possibly before the finalizer has a chance to run)?

... oh, maybe the GC lock gets held even after other threads get resumed, so the 
allocation will wait for finalizers to run? (just thought of that)

> Even with such precautions, a lock free implementation has one more problem: what happens if the memory block was released to the os? That's a segfault :( if other data is checked to avoid such situations, that's likely where gc locks come into the picture... I'm pretty sure Sean said querying the attribute bits requires a lock. It may be for this reason. I still have to look at the code though...

You mean it would segfault on checking the mark bit? Can't the GC just say the 
mark bit was not set for any pointer not pointing into a currently-allocated pool?
But yeah, checking if that address is part of an allocated pool may require 
holding the GC lock...



More information about the Digitalmars-d mailing list