Concurrency Confusion

"岩倉 澪" via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri Aug 7 15:13:33 PDT 2015


On Friday, 7 August 2015 at 15:55:33 UTC, Chris wrote:
> To stop threads immediately, I've found that the best way is to 
> use a shared variable, typically a bool, that is changed only 
> in one place.
> ...
> Unfortunately, sending an abort message to a thread as in 
> `send(thread, true)` takes too long. Setting a global flag like 
> ABORT is instantaneous. Beware of data races though. You might 
> want to have a look at:
>
> http://ddili.org/ders/d.en/concurrency_shared.html
>
> Especially `synchronized` and atomicOp.

Ah, I already had a variable like ABORT in my application for 
signaling the main thread to close, so this was a surprisingly 
painless change! I made that variable shared and then did the 
following:

instead of
     ABORT = true;
I now do
     import core.atomic;
     atomicStore!(MemoryOrder.rel)(ABORT, true);
and instead of
     if(ABORT) break;
I now do
     import core.atomic;
     if(atomicLoad!(MemoryOrder.acq)(ABORT)) break;

This works great, and with the memory ordering specified I do not 
see a noticeable difference in performance, whereas with the 
default memory ordering my ~36 second processing takes ~38 
seconds.

One concern I had was that `break` might be a bad idea inside of 
a parallel foreach. Luckily, it seems that the author(s) of 
std.parallelism thought of this - according to the documentation 
break inside of a parallel foreach throws an exception and some 
clever exception handling is done under the hood. I don't see an 
uncaught exception when I close my application, but it is now 
able to close without having to wait for the worker thread to 
complete, so everything seems fine and dandy! Thanks for the help!

On Friday, 7 August 2015 at 15:55:33 UTC, Chris wrote:
> receiveTimeout can be used like this: ...

My problem is that when you do this:

>         received = receiveTimeout(600.msecs,
>                                   (string message) {  // <=== 
> Receiving a value
>                                       writeln("received: ", 
> message);
>                                 });

"message" is local to the delegate that receiveTimeout takes.
I want to use "message" outside of the delegate in the receiving 
thread. However, if you send an immutable value from the worker 
thread, afaict there would be no way to assign it to a 
global/outer variable without making a mutable copy (expensive!)
I haven't really spent much time trying to pass my "message" as 
mutable via shared yet, but hopefully that could work...


More information about the Digitalmars-d-learn mailing list