See below.
In article <opsoqa0osi23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>>On Mon, 4 Apr 2005 22:08:16 +0000 (UTC), Larry Cowan <Larry_member@pathlink.com> wrote:
>> | module test;
>> | import std.thread;
>> | import std.stdio;
>> | import locks.countdown;
>> |
>> | void main ( char[][] args )
>> | {
>> | CountDownLatch allDone = new CountDownLatch(5);
>> | Thread[5] t;
>> |
>> | for (int i=0; i < 5 ;i++)
>> | t[i] = new Thread(
>> | delegate int() {
>> | printf(" thread %d\n",i);
>> | allDone.countDown();
>> | return 0;
>> | });
>> |
>> | printf("Starting threads.\n");
>> |
>> | for (int j=0; j < 5 ;j++)
>> | t[i].start();
>> |
>> | allDone.wait();
>> | printf("All done.\n");
>> |}
>>>> prints:
>>>> |Starting threads.
>> | thread 5
>> | thread 5
>> | thread 5
>> | thread 5
>> | thread 5
>> |All done.
>>>> How do I best do what I obviously want to? I can thnk of ways, but they are all somewhat convoluted and may be susceptible to similar problems. Do the delegates actually have their own (section of the?) stack?
>>In the above all the unnamed delegates share the same stack. Containing the same 'i' variable.
>>The dodgy bit, from where I'm sitting is that 'i' only exists for the duration of the for loop, so by the time you 'start' the threads... I must be missing something here? Perhaps the stack is not 'free'd (?) unless no more 'refences'(?) to it exist?
>Its not "free"ed, but it is reused, maybe j then uses the same place - the effect would be the same, but I can test this. Anyway, I know what is happening re the main() sction of the stack, but I was asking for an idea about how best to staticize the index for each thread, and I will try your "new"ing it idea, but the ref is still in main()'s stack area and may have the same problem.
>> Do I
>> have to make one for them on the heap to actually get independent
>> activity,
>> then have them pick up an index from a locked counter?
>Also I wanted assurance that when the threads actually
start they have independent stacks without my help - not just as if they
were called by main() and got the next stack frame - each getting the same
one.
>I would write a class i.e.
>>class Foo {
> int index;
> this(int i) { index = i; }
> .. run() ..
>}
>>then
>>| for (int i=0; i < 5 ;i++)
>| t[i] = new Thread(new Foo(i).run);
>>(not sure if the above is legal, but you get the idea?)
>>This should create a delegate that's object pointer points to a Foo class which has it's own 'index' integer, not shared between all the threads.
>>You could instead derive a clas from thread eg.
>>class Foo : Thread {
> int index;
> this(int i, ?delegate?) { super(?delegate?); index = i; }
> ~this() { allDone.countDown(); } // or maybe put this in the 'stop'(?)
>type method?
>}
>>"?delegate?" above as I cannot remember the syntax off hand.
>>Regan
I'll report back after some more experimenting...
-Larry

On Mon, 4 Apr 2005 22:42:21 +0000 (UTC), Larry Cowan <Larry_member@pathlink.com> wrote:
> In article <opsoqa0osi23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>> On Mon, 4 Apr 2005 22:08:16 +0000 (UTC), Larry Cowan
>> <Larry_member@pathlink.com> wrote:
>>> | module test;
>>> | import std.thread;
>>> | import std.stdio;
>>> | import locks.countdown;
>>> |
>>> | void main ( char[][] args )
>>> | {
>>> | CountDownLatch allDone = new CountDownLatch(5);
>>> | Thread[5] t;
>>> |
>>> | for (int i=0; i < 5 ;i++)
>>> | t[i] = new Thread(
>>> | delegate int() {
>>> | printf(" thread %d\n",i);
>>> | allDone.countDown();
>>> | return 0;
>>> | });
>>> |
>>> | printf("Starting threads.\n");
>>> |
>>> | for (int j=0; j < 5 ;j++)
>>> | t[i].start();
>>> |
>>> | allDone.wait();
>>> | printf("All done.\n");
>>> |}
>>>>>> prints:
>>>>>> |Starting threads.
>>> | thread 5
>>> | thread 5
>>> | thread 5
>>> | thread 5
>>> | thread 5
>>> |All done.
>>>>>> How do I best do what I obviously want to? I can thnk of ways, but they
>>> are all somewhat convoluted and may be susceptible to similar problems.
>>> Do the delegates actually have their own (section of the?) stack?
>>>> In the above all the unnamed delegates share the same stack. Containing
>> the same 'i' variable.
>>>> The dodgy bit, from where I'm sitting is that 'i' only exists for the
>> duration of the for loop, so by the time you 'start' the threads... I must
>> be missing something here? Perhaps the stack is not 'free'd (?) unless no
>> more 'refences'(?) to it exist?
>>> Its not "free"ed, but it is reused, maybe j then uses the same place - the
> effect would be the same, but I can test this.
Good point. This seems likely to me.
> Anyway, I know what is
> happening re the main() sction of the stack, but I was asking for an idea
> about how best to staticize the index for each thread, and I will try your
> "new"ing it idea, but the ref is still in main()'s stack area and may have
> the same problem.
No, my ideas do not use main()'s stack area. Each class is allocated on the heap, and the reference to the class is not stored except in the delegate passed to the threads constructor. (or in t[] if you extend Thread with your own class - which still means it is not stored in mains stack area - only the t[] reference is).
Either way the stack frame of the thread code is not main() it is the stack frame of the function in the class.
>>> Do I
>>> have to make one for them on the heap to actually get independent
>>> activity,
>>> then have them pick up an index from a locked counter?
>>> Also I wanted assurance that when the threads actually
> start they have independent stacks without my help - not just as if they
> were called by main() and got the next stack frame - each getting the same
> one.
IIRC creating an unnamed delegate assigns the current stack frame to the delegates object pointer.
So, creating an unnamed delegate in "main()" assigns mains stack frame to the delegate.
A class method delegate has it's object pointer assigned to the class instance.
The stack frame for a class delegate is the stack frame created when the method is called.
>> I would write a class i.e.
>>>> class Foo {
>> int index;
>> this(int i) { index = i; }
>> .. run() ..
>> }
>>>> then
>>>> | for (int i=0; i < 5 ;i++)
>> | t[i] = new Thread(new Foo(i).run);
>>>> (not sure if the above is legal, but you get the idea?)
>>>> This should create a delegate that's object pointer points to a Foo class
>> which has it's own 'index' integer, not shared between all the threads.
>>>> You could instead derive a clas from thread eg.
>>>> class Foo : Thread {
>> int index;
>> this(int i, ?delegate?) { super(?delegate?); index = i; }
>> ~this() { allDone.countDown(); } // or maybe put this in the 'stop'(?)
>> type method?
>> }
>>>> "?delegate?" above as I cannot remember the syntax off hand.
>>>> Regan
>> I'll report back after some more experimenting...
I am interested to know what you find. I have done very little experimentation with threads myself, so my advice may not be entirely acurate. IIRC Russ Lewis is the person I see most often posting about delegates and stack frames, his advice you can trust (I believe).
Regan

Glad to see someone using the Locks lib. When I was testing things out I ran into the same conundrum you did. A simple way (eg not very generic but it gets the job done) of solving the problem is to loop over t looking for the thread in question:
> | t[i] = new Thread(
> | delegate int() {
> | printf(" thread %d\n",i);
> | allDone.countDown();
> | return 0;
> | });
t[i] = new Thread(
delegate int() {
int n;
for(n=0;n<5;n++) {
if (Thread.getThis() is t[n]) break;
}
printf(" thread %d\n",n);
allDone.countDown();
return 0;
});