View mode: basic / threaded / horizontal-split · Log in · Help
November 09, 2005
Re: Threads and concurrency
Ben Hinkle wrote:
>>>After the loop, main waits only for the last created thread. Now, in real 
>>>code this would be dangerous because there's no guarantee that it 
>>>finishes last.
>>
>>Yup.  The code should probably do something like this instead:
>>
>>foreach( Thread t; Thread.getAll() )
>>    t.wait();
> 
> where "something like" doesn't actually call Thread.getAll(), right? 
> Glancing over std.thread getAll returns a slice of the static thread array 
> so its contents may change as the foreach loops over it - ie some elements 
> might be null if that thread happened to stop by the time the foreach got to 
> it.

Doh.  I'd forgotten about this particularly wonderful aspect of Phobos 
thread behavior.

> Also Thread.wait errors when you try to wait on yourself so since getAll 
> includes the current thread that loop will error at some point. 

So perhaps this then?

foreach( Thread t; Thread.getAll() )
	if( t && t != Thread.getThis() )
		t.wait();

A single pass still won't handle threads that are created during the 
loop, but the original example didn't do that anyway.


Sean
December 01, 2005
Re: Threads and concurrency
Anything on this Thread Tutorial? :-)

Can anyone point me to a nice D thread sample?  I need to start using more CPU.

thanks.

jose

Charles says...
>
>And if I can get a couple simple Thread examples working I'll post a (hopefully
>useful) D Thread tutorial ...
>
>In article <dkrbiu$17v1$1@digitaldaemon.com>, Charles says...
>>
>>While on the subject of Threads would someone please hit me w/ the clue bat b/c
>>I can't seem to get the following working. This example should just call
>>mthread.run since I've overloaded it . But that's not what happens. It just call
>>
>>the mthread constructor and finishes. I'd also appreciate any links to some
>>beginner Thread examples in D. I'm sure the locks code would come in handy at
>>some point but I'm not there yet.
>>
>>int main () {
>>mthread m = new Thread();
>>m.run(); // <== this should call mthread.run but it just calls the constructor
>>
>>return 0;
>>}
>>
>>
>>module mthread;
>>import std.thread;
>>
>>class mthread : Thread {
>>this () {
>>super();
>>std.string.writefln("S thread cons");
>>std.string.writefln("E thread cons");
>>}
>>
>>~this() { }
>>
>>int run () { foo(); }
>>
>>void foo () {
>>std.string.writefln("inside foo");
>>}
>>void bar () {
>>std.string.writefln("inside bar");
>>}
>>}
>>
>>
>
>
December 01, 2005
Re: Threads and concurrency
On Tue, 8 Nov 2005 23:15:42 +0000 (UTC), Charles wrote:

> While on the subject of Threads would someone please hit me w/ the clue bat b/c
> I can't seem to get the following working...

I don't blame you...the documentation is very unhelpful. I've been playing
with thread for an hour now and I can't get to do much useful work. Has
anyone got some novice-oriented documentation on D threads?

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"A learning experience is one of those things that says,
'You know that thing you just did? Don't do that.'" - D.N. Adams
1/12/2005 5:35:32 PM
December 01, 2005
Re: Threads and concurrency
Derek Parnell wrote:
> On Tue, 8 Nov 2005 23:15:42 +0000 (UTC), Charles wrote:
> 
>> While on the subject of Threads would someone please hit me w/ the clue bat b/c
>> I can't seem to get the following working...
> 
> I don't blame you...the documentation is very unhelpful. I've been playing
> with thread for an hour now and I can't get to do much useful work. Has
> anyone got some novice-oriented documentation on D threads?

I'll outline how threads are used in Ares and I expect 95% of it will 
apply to Phobos as well.  There are two basic ways to handle 
multithreading in D, subclassing Thread or passing a function pointer to 
a new thread object on construction.  Subclassing can be a risky 
proposition in C++ and other languages without garbage collection 
because the Thread object may be destroyed before the thread completes. 
 As D has GC however, this isn't an issue, and I find subclassing to be 
the most natural way to deal with multithreading in most cases.  The 
function pointer method tend to be quite useful when adapting existing 
code or when you aren't entirely sure whether you will need to 
parallelize a certain function or not.  Here is a short example of how 
to create, run, and wait for threads in D:


import std.thread;
import std.c.stdio;

class MyThread : Thread
{
    // the signature of run() might be different in Phobos--
    // I believe it returns an int or uint
    void run()
    {
        printf( "Hello from MyThread\n" );
    }
}

void threadFunc()
{
    printf( "Hello from threadFunc\n" );
}

void main()
{
    int i = 5;

    void threadDelegate()
    {
        printf( "threadDelegate can see i = %i\n", i );
    }

    MyThread mt = new MyThread();
    Thread   tf = new Thread( &threadFunc );
    Thread   td = new Thread( &threadDelegate );

    // threads must be started explicitly
    mt.start();
    tf.start();
    td.start();

    // you must wait for the threads to complete if you want to
    // be sure their output is displayed
    mt.join(); // join() is called waitFor() in Phobos
    tf.join();
    td.join();
}

C:\code\d>dmd test
C:\bin\dmd\bin\..\..\dm\bin\link.exe test,,,user32+kernel32/noi;

C:\code\d>test
Hello from MyThread
Hello from threadFunc
threadDelegate can see i = 5



When a thread in started, it is guaranteed to see any data changes made 
by the starting thread before the start() call, so threadDelegate is 
guaranteed to see i as 5.  If you intend to subsequently change the 
value of i however, accesses should be done within a synchronized block. 
 The purpose of 'volatile' in D is basically to preserve code order 
when lock-free concurrency is desired, so be aware that it provides no 
memory visibility guarantees like 'volatile' in C++ is (mistakenly) said 
to.  That's all I can think of offhand.  If you have any more specific 
questions, I'd be happy to answer them.


Sean
December 01, 2005
Re: Threads and concurrency
I'll just add that subclassing Thread allows one to naturally create their 
own TLS (thread local storage). The alternate method, where TLS is supported 
via an int[] or something similar,  requires some less-than-clear 
bit-stuffing to achieve the equivalent.

- Kris



"Sean Kelly" <sean@f4.ca> wrote in message 
news:dmm954$2e4t$1@digitaldaemon.com...
> Derek Parnell wrote:
>> On Tue, 8 Nov 2005 23:15:42 +0000 (UTC), Charles wrote:
>>
>>> While on the subject of Threads would someone please hit me w/ the clue 
>>> bat b/c
>>> I can't seem to get the following working...
>>
>> I don't blame you...the documentation is very unhelpful. I've been 
>> playing
>> with thread for an hour now and I can't get to do much useful work. Has
>> anyone got some novice-oriented documentation on D threads?
>
> I'll outline how threads are used in Ares and I expect 95% of it will 
> apply to Phobos as well.  There are two basic ways to handle 
> multithreading in D, subclassing Thread or passing a function pointer to a 
> new thread object on construction.  Subclassing can be a risky proposition 
> in C++ and other languages without garbage collection because the Thread 
> object may be destroyed before the thread completes. As D has GC however, 
> this isn't an issue, and I find subclassing to be the most natural way to 
> deal with multithreading in most cases.  The function pointer method tend 
> to be quite useful when adapting existing code or when you aren't entirely 
> sure whether you will need to parallelize a certain function or not.  Here 
> is a short example of how to create, run, and wait for threads in D:
>
>
> import std.thread;
> import std.c.stdio;
>
> class MyThread : Thread
> {
>     // the signature of run() might be different in Phobos--
>     // I believe it returns an int or uint
>     void run()
>     {
>         printf( "Hello from MyThread\n" );
>     }
> }
>
> void threadFunc()
> {
>     printf( "Hello from threadFunc\n" );
> }
>
> void main()
> {
>     int i = 5;
>
>     void threadDelegate()
>     {
>         printf( "threadDelegate can see i = %i\n", i );
>     }
>
>     MyThread mt = new MyThread();
>     Thread   tf = new Thread( &threadFunc );
>     Thread   td = new Thread( &threadDelegate );
>
>     // threads must be started explicitly
>     mt.start();
>     tf.start();
>     td.start();
>
>     // you must wait for the threads to complete if you want to
>     // be sure their output is displayed
>     mt.join(); // join() is called waitFor() in Phobos
>     tf.join();
>     td.join();
> }
>
> C:\code\d>dmd test
> C:\bin\dmd\bin\..\..\dm\bin\link.exe test,,,user32+kernel32/noi;
>
> C:\code\d>test
> Hello from MyThread
> Hello from threadFunc
> threadDelegate can see i = 5
>
>
>
> When a thread in started, it is guaranteed to see any data changes made by 
> the starting thread before the start() call, so threadDelegate is 
> guaranteed to see i as 5.  If you intend to subsequently change the value 
> of i however, accesses should be done within a synchronized block. The 
> purpose of 'volatile' in D is basically to preserve code order when 
> lock-free concurrency is desired, so be aware that it provides no memory 
> visibility guarantees like 'volatile' in C++ is (mistakenly) said to. 
> That's all I can think of offhand.  If you have any more specific 
> questions, I'd be happy to answer them.
>
>
> Sean
December 01, 2005
Re: Threads and concurrency
Kris wrote:
> I'll just add that subclassing Thread allows one to naturally create their 
> own TLS (thread local storage). The alternate method, where TLS is supported 
> via an int[] or something similar,  requires some less-than-clear 
> bit-stuffing to achieve the equivalent.

Agreed.  It can be appropriate for some algorithms but I wouldn't 
suggest it as the default storage choice.  I've also heard the Posix 
implementation of TLS is a tad slow, though Windows TLS should be quite 
decent.  For what it's worth, Thread.getThis() in Ares is implemented 
using TLS to avoid the need to access the global thread list.


Sean
December 01, 2005
Re: Threads and concurrency
"Sean Kelly" <sean@f4.ca> wrote
>  For what it's worth, Thread.getThis() in Ares is implemented using TLS to 
> avoid the need to access the global thread list.

Nice.
December 02, 2005
Re: Threads and concurrency
On Wed, 30 Nov 2005 23:35:56 -0800, Sean Kelly wrote:

> Derek Parnell wrote:
>> On Tue, 8 Nov 2005 23:15:42 +0000 (UTC), Charles wrote:
>> 
>>> While on the subject of Threads would someone please hit me w/ the clue bat b/c
>>> I can't seem to get the following working...
>> 
>> I don't blame you...the documentation is very unhelpful. I've been playing
>> with thread for an hour now and I can't get to do much useful work. Has
>> anyone got some novice-oriented documentation on D threads?
> 
> I'll outline how threads are used in Ares and I expect 95% of it will 
> apply to Phobos as well. 

But back in Phobos-land ... I managed to make something that I understand
what is going on. There are two files here...

===== mthread.d ===========
module mthread;
import std.thread;
import std.stdio;
import std.c.windows.windows;

class mthread : Thread
{
   private{
       static int g_id;
       static const uint OneSecond = 1000;
       int m_id;
       int m_V;
   }

   this (int V)
   {
       m_id = ++g_id;
       m_V = V;

       // Register callback function with Thread Central.
       super(&thread_main);

       writefln("create thread #%d", m_id);
   }

   ~this()
   {
       writefln("destroy thread #%d", m_id);
   }

   int id()
   {
       return m_id;
   }

   int init_value()
   {
       return m_V;
   }

   int thread_main ()
   {
       writefln("in  thread_main #%d", m_id);
       for(int i = 0; i < m_V; i++)
       {
           Sleep(OneSecond); // Do something very important
           yield();  // Let someone else have some play time.
       }
       writefln("out thread_main #%d", m_id);
       return 0;
   }

}

===== test.d  =============
import mthread;
import std.math;

int main ()
{
   mthread m[];
   uint allDone = 0;
   uint doneFlag;

   // Create some threads of different durations.
   m ~= new mthread(5);
   m ~= new mthread(7);
   m ~= new mthread(2);
   m ~= new mthread(4);

   doneFlag = cast(uint)pow(2.0l, m.length)-1;

   // Start all the threads running
   foreach(mthread t; m)
   {
       writefln("Starting #%d for %d seconds", t.id, t.init_value);
       t.start();
   }

   // Hang around until they all finish.
   while (allDone != doneFlag)
   {
       foreach(int i, mthread t; m)
       {
           if (t.getState == Thread.TS.TERMINATED)
           {
               uint old;
               old = allDone;
               allDone |= cast(uint)pow(2.0l,i);
               if (old != allDone)
                   writefln("Finished #%d after %d seconds", t.id,
t.init_value);
           }
       }
   }

   writefln("done");


   // Ensure that they clean up.
   foreach(int i, mthread t; m)
   {
       writefln("final wait #%d", t.id);
       t.wait();
       delete t;
   }

   return 0;
}

===========================

And I ran "build test -run" to get ...

C:\temp>build test -run
Path and Version : y:\util\build.exe v2.9(1197)
 built on Wed Aug 10 11:03:42 2005
y:\dmd\bin\..\..\dm\bin\link.exe
test+mthread,test.exe,,user32+kernel32,test.def
/noi;
create thread #1
create thread #2
create thread #3
create thread #4
Starting #1 for 5 seconds
Starting #2 for 7 seconds
Starting #3 for 2 seconds
Starting #4 for 4 seconds
in  thread_main #1
in  thread_main #2
in  thread_main #3
in  thread_main #4
out thread_main #3
Finished #3 after 2 seconds
out thread_main #4
Finished #4 after 4 seconds
out thread_main #1
Finished #1 after 5 seconds
out thread_main #2
Finished #2 after 7 seconds
done
final wait #1
destroy thread #1
final wait #2
destroy thread #2
final wait #3
destroy thread #3
final wait #4
destroy thread #4

C:\temp>

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"A learning experience is one of those things that says,
'You know that thing you just did? Don't do that.'" - D.N. Adams
2/12/2005 3:17:07 PM
December 02, 2005
Re: Threads and concurrency
In article <137ig7kvpvpus$.1a7ft4fbi03n0$.dlg@40tude.net>, Derek Parnell says...
>
>On Tue, 8 Nov 2005 23:15:42 +0000 (UTC), Charles wrote:
>
>> While on the subject of Threads would someone please hit me w/ the clue bat b/c
>> I can't seem to get the following working...
>
>I don't blame you...the documentation is very unhelpful. I've been playing
>with thread for an hour now and I can't get to do much useful work. Has
>anyone got some novice-oriented documentation on D threads?

I haven't tried running this recently, but I got this to work in the past:
http://trac.dsource.org/projects/tutorials/wiki/ThreadsExample

jcc7
Next ›   Last »
1 2
Top | Discussion index | About this forum | D home