Closure/Stack-to-Heap Semantics

Bruno Medeiros brunodomedeiros+spam at com.gmail
Fri Oct 3 05:40:13 PDT 2008


dsimcha wrote:
> If I write a loop, and want to submit each iteration of that loop to its own
> thread, or to a thread pool or something, how do I get D to copy the current
> stack frame to the heap each time I use the delegate?  For example:
> 
> import std.thread, std.stdio, std.c.time;
> 
> void main() {
>     Thread[] myThreads = new Thread[100];
>     foreach(i; 0..100) {
>         auto T = new Thread({
>             sleep(1);  //Give i time to be incremented to 100.
>             writeln(i);
>             return 0;
>         });
>         T.start;
>         myThreads[i] = T;
>     }
>     foreach(T; myThreads) {
>         T.wait;
>     }
> }
> 
> This program prints out all 100's because by the time each thread is done
> sleeping, i = 100.  How do I make D copy the stack context each time I submit
> a delegate to a thread, in similar fashion to a closure?

Your code is correct and should work as you expect. It doesn't only 
because of a bug: http://d.puremagic.com/issues/show_bug.cgi?id=2043
The workaround is to envelop the foreach body in a function, as 
explained in the report.

Strangely, you'll run into another bug: writefln is not thread-safe!? 
You will have to envelop it with a synchronized statement. So the code 
looks like this:

     foreach(i; 0..100) {
         (int i) {
             writeln("(BEGIN) i: ", i, " &i: ", &i);
             auto T = new Thread({
                 sleep(1);  //Give i time to be incremented to 100.
                 synchronized {
                     writeln("i: ", i, " &i: ", &i);
                 }
                 return 0;
             });
             T.start;
             myThreads[i] = T;
         } (i);
     }




-- 
Bruno Medeiros - Software Developer, MSc. in CS/E graduate
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D



More information about the Digitalmars-d mailing list