What's the go with the GC these days?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Mon Jan 7 21:53:50 UTC 2019


On Monday, January 7, 2019 1:48:04 PM MST Neia Neutuladh via Digitalmars-d 
wrote:
> On Mon, 07 Jan 2019 11:52:18 -0800, H. S. Teoh wrote:
> > I think what Neia has in mind, which he mentioned in another post, is to
> > have the druntime function simply pin the object, whichever pool it
> > belongs to.  The idea being to tell the respective thread-local GC "this
> > object might be referenced by another thread, do not collect or move".
>
> She, not he.
>
> Thinking about this some more, this strategy isn't as cheap or easy as I
> was hoping. Let's say you're using fearless:
>
> auto a = gcExclusive!Node;
> spawn({
>   {
>     auto tmp = a.lock;
>     tmp.parent = new Object;
>   }
>   GC.threadLocal.collect();
>   GC.threadLocal.minimize();
>   {
>     auto tmp = a.lock;
>     writeln(tmp.parent.toString);
>   }
> });
>
> Where do we insert the runtime call to mark a.parent as shared? Fearless
> would have to:
> 1. Acquire the mutex
> 2. Tell the current thread's GC to add the locked object as a root
> 3. Run your code
> 4. Tell the thread's GC to pin everything it can find from `a` (by casting
> back to shared)
> 5. Release the mutex
>
> This effectively incurs a mark (but not sweep) cycle every time you cast
> to shared. If it were just pinning one object, that would be a lot easier
> to sell.

Casting between shared and thread-local doesn't have to be free, but it
cannot be expensive, because unless you're using atomics, the way that it's
designed pretty much requires that you cast away shared (after locking a
mutex to protect the object) in order to operate on it. So, if casting away
shared is expensive, then code using shared gets screwed.

Also, there isn't anything stopping a programmer from assigning a
thread-local reference to something inside an object that has had shared
cast away, and there likely isn't any reason for the programmer to cast
anything to shared in that scenario. They'd just get rid of the thread-local
reference to the shared object before releasing the mutex, meaning that the
runtime couldn't even see that what had been assigned to one of its
internals had gone from being treated as thread-local to shared. Having
objects go from shared to thread-local in such code could be possible as
well if a reference is taken from the object which has had shared cast away
and then stored as thread-local. In fact that sort of scenario is pretty
much exactly what would happen with something like a consumer-producer
queue. Programmers dealing with shared need to be aware of such things and
deal with them appropriately in order to avoid having problems (which is
part of why casting away shared has to be @trusted), but it's perfectly
legal so long as no shared object is ever treated as thread-local when it
can actually be operated on by multiple threads, and no thread-local objects
end up on multiple threads at the same time. Given that sort of situation, I
don't see how we can have the GC accurately track whether objects are
thread-local or shared. Casting is just too blunt an instrument and allows
too much.

- Jonathan M Davis





More information about the Digitalmars-d mailing list