D2 weak references

Jason House jason.james.house at gmail.com
Thu Apr 23 13:48:12 PDT 2009


Leandro Lucarella Wrote:

> Jason House, el 23 de abril a las 12:51 me escribiste:
> > > >     T opCall(){
> > > >         T tmp = t; // force future conservative GC scan to find the pointer
> > > >         if ( (tmp is null) || (pool.mark[index] == false) ){
> > > 
> > > pool.mark.test(index) is used in the GC code, I don't know if the array
> > > syntax works. And to use the mark bit trick, I think something in the
> > > lines of my patch is needed to ensure the mark bit is set for all live
> > > objects.
> > > 
> > > >             t = null;
> > > >             return null;
> > > >         }
> > > >         tmp = t; // avoid race where t was replaced with new data
> > > 
> > > I don't understand exactly what kind of race are you trying to avoid with
> > > this (and how this assignation can avoid any race if there is one).
> > 
> > Consider this sequence:
> > 1. GC runs mark phase and leaves object unmarked.
> > 2. Weakref starts dereferencing and reads its hidden pointer.
> 
> Ok, I see now that this can happen because you first store the reference
> into the stack so it can be seen in future collections.

Yeah.


> What I'm not sure is if it's really necessary to do that step. What can go
> wrong with this simple approach?
> 
>      T opCall() {
>          if (!pool.mark.test(index))
>              t = null;
>          return t;
>      }

What happens when a collection runs after test returns? You need to copy t onto the stack in order to be safe.

> Weakref only reads the reference *if* the mark bit is set, in which case
> is safe to assume that the object is live.

How do you check the mark bit? In the sample code, it used the reference... Admittedly, one could store the right info to avoid that, but it hardly matters.


> If the object is garbage, the mark bit is unset and in that case the
> reference is only *written* (the only race it could happen is the sweep()
> can be called but in that case the reference is written to null too, so
> there should be no problem with that, I guess...
> 
> As long as the test are successful (t is not overwritten to null), the GC
> should be able to find the reference in the stack when the function
> returns.
> 
> I'm probably missing something else...

You're not considering what can happen if the weak ref dereferencing thread stops and the rest of the world wreaks havoc on the state of the world. A collection could run after checking the mark. If one is careful with that, and a copy of t is kept on the stack, will the optimizer reuse it? Or will it reread the value? That matters if the finalizer runs. The mark bit check can fail from reallocation after deletion.

I hope that helps...



> > 3. Sweep calls finalizer and deallocates
> > 4. A new object is allocated in the old location
> > 5. Query for GC mark says we're ok
> > 6. Weakref returns its old copy of the pointer
> > 7. Pointer is used
> > 8. Random behavior
> 
> -- 
> Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/
> ----------------------------------------------------------------------------
> GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
> ----------------------------------------------------------------------------




More information about the Digitalmars-d mailing list