digitalmars.D.learn - Threads and concurrency
- Charles (28/28) Nov 08 2005 While on the subject of Threads would someone please hit me w/ the clue ...
- Charles (3/31) Nov 08 2005 And if I can get a couple simple Thread examples working I'll post a (ho...
- jicman (5/48) Nov 30 2005 Anything on this Thread Tutorial? :-)
- Sean Kelly (6/13) Nov 08 2005 I'm surprised this is even allowed. You're constructing an instance of
- Charles (34/38) Nov 08 2005 Sean, thanks for the reply. I've corrected the code to allocate an mthre...
- Sean Kelly (24/24) Nov 08 2005 Try this:
- Charles (2/26) Nov 08 2005
- Charles (13/54) Nov 08 2005 okay, I solved my own problem ... I forgot to call wait() ... christ.
- Georg Wrede (19/88) Nov 09 2005 I hope the above code was just "a sketch" thrown in, since I don't think...
- Sean Kelly (5/41) Nov 09 2005 Yup. The code should probably do something like this instead:
- Ben Hinkle (6/12) Nov 09 2005 where "something like" doesn't actually call Thread.getAll(), right?
- Sean Kelly (10/26) Nov 09 2005 Doh. I'd forgotten about this particularly wonderful aspect of Phobos
- Derek Parnell (11/13) Nov 30 2005 I don't blame you...the documentation is very unhelpful. I've been playi...
- Sean Kelly (64/72) Nov 30 2005 I'll outline how threads are used in Ares and I expect 95% of it will
- Kris (7/80) Nov 30 2005 I'll just add that subclassing Thread allows one to naturally create the...
- Sean Kelly (7/11) Dec 01 2005 Agreed. It can be appropriate for some algorithms but I wouldn't
- Kris (2/4) Dec 01 2005 Nice.
- Derek Parnell (139/151) Dec 01 2005 But back in Phobos-land ... I managed to make something that I understan...
- J C Calvarese (4/10) Dec 02 2005 I haven't tried running this recently, but I got this to work in the pas...
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"); } }
Nov 08 2005
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"); } }
Nov 08 2005
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"); } }
Nov 30 2005
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. 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....int main () { mthread m = new Thread();I'm surprised this is even allowed. You're constructing an instance of the base class, not mthread. Try this: mthread m = new mthread(); Sean
Nov 08 2005
In article <dkrd8s$19km$1 digitaldaemon.com>, Sean Kelly says...I'm surprised this is even allowed. You're constructing an instance of the base class, not mthread. Try this: mthread m = new mthread(); SeanSean, thanks for the reply. I've corrected the code to allocate an mthread() and I still get the same output. Here's my makefile,main.d and mthread.d . I don't think I can think of a simpler example than this ... D = gdc main: main.d mthread.o $(D) -o main main.d mthread.o mthread.o: mthread.d $(D) -o mthread.o -c mthread.d c clean: rm -f ./*.o import mthread; int main () { mthread m = new mthread(); m.start(); 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"); } }
Nov 08 2005
Try this: import std.thread; import std.c.stdio; class mthread : Thread { int run () { foo(); return 0; } void foo () { printf( "inside foo\n" ); } } void main() { mthread m = new mthread(); m.start(); m.wait(); } The problem was tha you didn't have the m.wait() line at the end of main so the program was ending before your thread had started. Sean
Nov 08 2005
Thanks!! In article <dkrfmi$1c1a$1 digitaldaemon.com>, Sean Kelly says...Try this: import std.thread; import std.c.stdio; class mthread : Thread { int run () { foo(); return 0; } void foo () { printf( "inside foo\n" ); } } void main() { mthread m = new mthread(); m.start(); m.wait(); } The problem was tha you didn't have the m.wait() line at the end of main so the program was ending before your thread had started. Sean
Nov 08 2005
okay, I solved my own problem ... I forgot to call wait() ... christ. Here my new main.d import mthread; int main () { mthread m; for( int i;i<10;i++) { m = new mthread(i); m.start(); } m.wait(); return 0; } In article <dkre89$1alk$1 digitaldaemon.com>, Charles says...In article <dkrd8s$19km$1 digitaldaemon.com>, Sean Kelly says...I'm surprised this is even allowed. You're constructing an instance of the base class, not mthread. Try this: mthread m = new mthread(); SeanSean, thanks for the reply. I've corrected the code to allocate an mthread() and I still get the same output. Here's my makefile,main.d and mthread.d . I don't think I can think of a simpler example than this ... D = gdc main: main.d mthread.o $(D) -o main main.d mthread.o mthread.o: mthread.d $(D) -o mthread.o -c mthread.d c clean: rm -f ./*.o import mthread; int main () { mthread m = new mthread(); m.start(); 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"); } }
Nov 08 2005
Charles wrote:okay, I solved my own problem ... I forgot to call wait() ... christ. Here my new main.d import mthread; int main () { mthread m; for( int i;i<10;i++) { m = new mthread(i); m.start(); } m.wait(); return 0; }I hope the above code was just "a sketch" thrown in, since I don't think it is quite right? ((Somebody correct me if I'm wrong here: )) In the for loop: - you create a thread - you start the thread - you abandon the thread by assigning a new one to m - thus you can't reach any of the previously created threads Luckily, ;-( the previous threads don't get reaped by the GC, because std.thread itself has to keep pointers to them. (And you can always issue Thread.getAll() to get all the running threads, but it's not a substitute for properly being able to e.g. pause, wait, or resume a specific known thread.) 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. So, while the above code probably "works", it should be corrected by somebody better versed (than me) in threads.In article <dkre89$1alk$1 digitaldaemon.com>, Charles says...In article <dkrd8s$19km$1 digitaldaemon.com>, Sean Kelly says...I'm surprised this is even allowed. You're constructing an instance of the base class, not mthread. Try this: mthread m = new mthread(); SeanSean, thanks for the reply. I've corrected the code to allocate an mthread() and I still get the same output. Here's my makefile,main.d and mthread.d . I don't think I can think of a simpler example than this ... D = gdc main: main.d mthread.o $(D) -o main main.d mthread.o mthread.o: mthread.d $(D) -o mthread.o -c mthread.d c clean: rm -f ./*.o import mthread; int main () { mthread m = new mthread(); m.start(); 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"); } }
Nov 09 2005
Georg Wrede wrote:Charles wrote:Yup. The code should probably do something like this instead: foreach( Thread t; Thread.getAll() ) t.wait(); Seanokay, I solved my own problem ... I forgot to call wait() ... christ. Here my new main.d import mthread; int main () { mthread m; for( int i;i<10;i++) { m = new mthread(i); m.start(); } m.wait(); return 0; }I hope the above code was just "a sketch" thrown in, since I don't think it is quite right? ((Somebody correct me if I'm wrong here: )) In the for loop: - you create a thread - you start the thread - you abandon the thread by assigning a new one to m - thus you can't reach any of the previously created threads Luckily, ;-( the previous threads don't get reaped by the GC, because std.thread itself has to keep pointers to them. (And you can always issue Thread.getAll() to get all the running threads, but it's not a substitute for properly being able to e.g. pause, wait, or resume a specific known thread.) 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.
Nov 09 2005
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. 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.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();
Nov 09 2005
Ben Hinkle wrote:Doh. I'd forgotten about this particularly wonderful aspect of Phobos thread behavior.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.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();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
Nov 09 2005
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
Nov 30 2005
Derek Parnell wrote:On Tue, 8 Nov 2005 23:15:42 +0000 (UTC), Charles wrote: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. SeanWhile 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?
Nov 30 2005
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: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. SeanWhile 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?
Nov 30 2005
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
Dec 01 2005
"Sean Kelly" <sean f4.ca> wroteFor what it's worth, Thread.getThis() in Ares is implemented using TLS to avoid the need to access the global thread list.Nice.
Dec 01 2005
On Wed, 30 Nov 2005 23:35:56 -0800, Sean Kelly wrote:Derek Parnell wrote: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); } ~this() { } int id() { return m_id; } int init_value() { return m_V; } int thread_main () { for(int i = 0; i < m_V; i++) { Sleep(OneSecond); // Do something very important yield(); // Let someone else have some play time. } 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) { 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) t.init_value); } } } writefln("done"); // Ensure that they clean up. foreach(int i, mthread t; m) { 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; done 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 PMOn Tue, 8 Nov 2005 23:15:42 +0000 (UTC), Charles wrote:I'll outline how threads are used in Ares and I expect 95% of it will apply to Phobos as well.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?
Dec 01 2005
In article <137ig7kvpvpus$.1a7ft4fbi03n0$.dlg 40tude.net>, Derek Parnell says...On Tue, 8 Nov 2005 23:15:42 +0000 (UTC), Charles wrote:I haven't tried running this recently, but I got this to work in the past: http://trac.dsource.org/projects/tutorials/wiki/ThreadsExample jcc7While 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?
Dec 02 2005