Is GC.setAttr(p, GC.BlkAttr.NO_MOVE) guaranteed to work?

Rainer Schuetze via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Jul 1 23:45:02 PDT 2014



On 02.07.2014 08:17, Ali Çehreli wrote:
> There is an example in GC.addRoot() documentation where the programmer
> is trying to mark a memory block as NO_MOVE:
>
>    http://dlang.org/phobos/core_memory.html#.GC.addRoot
>
>      auto context = new Object;
>      GC.addRoot(cast(void*)context);
>      GC.setAttr(cast(void*)context, GC.BlkAttr.NO_MOVE);
>
> If I understand it correctly, as soon as addRoot() succeeds, the block
> may have already been moved perhaps due to the needs of another thread.

Yes, but the local variable "context" also has been changed to the new 
location by a moving GC (also any temporaries on the stack).

>
> Will setAttr() still work if that happened? Perhaps the GC is supposed
> to track any previously used memory block reference like 'context' so
> that the call will succeed? (I doubt it.)
>
> If the example can indeed fail, will swapping the last two statements
> work as in the following code?
>
>      auto context = new Object;
>      GC.setAttr(cast(void*)context, GC.BlkAttr.NO_MOVE);
>      GC.addRoot(cast(void*)context);
>
> How about the reverse operations: Can I still use 'ctx' to refer to
> potentially moved memory block in the following code?
>
>      GC.removeRoot(ctx);
>      GC.clrAttr(ctx, GC.BlkAttr.NO_MOVE);
>
> It seems to me that as a general rule, one cannot trust setting NO_MOVE
> on a GC-managed block at all. If that's true, addRoot() must have an
> overload that takes attributes as well and work atomically in that
> regard, right?
>
> Ali

addRoot tells the GC that there are external references into GC managed 
memory. These references are not visible to the GC, so it cannot modify 
them when moving the referenced memory. As a consequence, addRoot 
implies NO_MOVE. I think the example is flawed.

The issue raised does show a rule to follow, though: do not store a GC 
pointer to external memory before calling addRoot() or setAttr(NO_MOVE), 
it might get moved after the assignment, but before being fixed.

BTW: The current GC has no support for moving, and the NO_MOVE flag 
isn't even stored anywhere (getAttr after setAttr will not report it 
being set).



More information about the Digitalmars-d-learn mailing list