Aliases to mutable thread-local data not allowed [testable source code]

Simen Kjærås simen.kjaras at gmail.com
Wed Mar 11 08:49:39 UTC 2020


On Tuesday, 10 March 2020 at 20:03:21 UTC, mark wrote:
> I've managed to make a cut-down version that's < 170 LOC.
> It needs to be run on Debian or a Debian-based Linux (e.g., 
> Ubuntu).
>
> Hopefully this will help someone understand and be able to help!

This took some time figuring out. Turns out, 
std.concurrency.spawn won't take a delegate as its callable 
argument. There are sensible reasons for this - delegates have a 
context that is not guaranteed to be immutable, so allowing 
delegate callables could lead to mutable aliasing. I've filed an 
issue to improve documentation and error messages: 
https://issues.dlang.org/show_bug.cgi?id=20665

However, knowing that some things are impossible do not 
necessarily help us figure out what we can do to fix the problem, 
and the good news is, the problems can be fixed. Since the 
problem is we're giving a delegate where the API expects a 
function, we can simply turn it into a function. In the code 
you've given, that means making readPackageFile and 
readPackageLine static. This make spawn() run as it should.

In addition, there's a problem with this line in receive():

     (DoneMessage) { jobs--; }

That looks sensible, but since DoneMessage doesn't have a name, 
it is parsed as a templated function taking one argument of 
unspecified type and called DoneMessage. For some reason, 
templates passed as function arguments show up in compiler output 
as 'void', giving this weird error message:

     template std.concurrency.receive cannot deduce function from 
argument types !()(void delegate(Deb deb) pure nothrow @safe, 
void)

The solution here is to simply give DoneMessage a name:

     (DoneMessage d) { jobs--; }

With those changes, things at least compile. Now it's up to you 
to ensure the semantics are correct. :)

One last thing: you're passing parentTid around, and that's not 
actually necessary - std.concurrency.ownerTid does the exact same 
thing, and is available even if not explicitly passed anywhere.

--
   Simen


More information about the Digitalmars-d-learn mailing list