can I force a parallel foreach to finish?

Steven Schveighoffer schveiguy at yahoo.com
Mon Jul 25 07:04:00 PDT 2011


On Fri, 22 Jul 2011 18:38:15 -0400, McAnany, Charles E  
<mcanance at rose-hulman.edu> wrote:

> Hi, all. So I'm getting the classic "concurrency noob" behavior from  
> this code:
>     shared int times;
>     int[] iterationRange = new int[2500];
>     foreach (pos, ref  i; parallel(iterationRange)){
>         times++;
>     }
>     writeln(times);
> }
> Prints random numbers near 1,000.
> Looking at the documentation for std.concurrency, it appears that when  
> dealing with tasks, you have to yieldForce to get them to finish. Is  
> there a method that blocks until taskPool itself is empty?

I think you are misreading something, std.concurrency does not have to do  
with std.parallelism

Note that while compiler inserts memory barriers around operations on  
shared data, it does not get rid of race issues.  That is, times++ is  
*not* atomic, so you cannot expect it to avoid races.

Try:
import core.atomic;

atomicOp!"+="(times, 1);

> I think the problem is not concurrent modification, the foreach just  
> seems to return too early, as seen here:
>
> int times;
> void shareAugmenter(){
>     bool cont = true;
>     while(cont){
>         receive( (int i){times++;},
>                  (string s){writefln("in the thread %s",times);cont =  
> false;});
>     }
> }
> void main(string[] args){
>    auto td = spawn(&shareAugmenter);
>     int[] iterationRange = new int[2500];
>     foreach (pos, ref  i; parallel(iterationRange)){
>         td.send(1);
>     }
>     writeln(times);
>     td.send("");
>     writeln(times);
> prints
> 0
> 0
> In the thread 2500

Note that int times is THREAD LOCAL, so essentially you have created two  
separate copies of times, one in the main thread and one in the sub thread.

Change the declaration to:

shared int times;

-Steve


More information about the Digitalmars-d-learn mailing list