digitalmars.D.learn - How are theads, Tid and spawn related?
- Neven (7/7) Nov 01 2014 Ok, a newbie question ahead. I want to create new thread which
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (22/29) Nov 01 2014 You don't need a Thread object to wait for a thread to finish. One
- Sean Kelly (12/12) Nov 01 2014 Note that thread_joinAll is called automatically when main exits,
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (6/7) Nov 01 2014 Has that always been the case? I remember having to inject
- Sean Kelly (8/16) Nov 02 2014 It has always been the case. In fact, I have a comment in the
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (22/28) Nov 02 2014 I've grepped for thread_joinAll calls in my examples and identified two
- Sean Kelly (3/3) Nov 02 2014 For those cases you could use spawnLinked and then receive
- Sean Kelly (12/12) Nov 01 2014 Note that thread_joinAll is called automatically when main exits,
- Russel Winder via Digitalmars-d-learn (23/31) Nov 02 2014 Modern thinking is that threads are managed infrastructure that
Ok, a newbie question ahead. I want to create new thread which calls given function with some parameters. Thus, I think spawn is the right function for me. However that functions returns Tid and not a Thread object. So I want to know how can I make a Thread object out of it. What I would like to achieve is to wait for spawned thread to finish its execution, that is join with main thread.
Nov 01 2014
On 11/01/2014 04:32 PM, Neven wrote:Ok, a newbie question ahead. I want to create new thread which calls given function with some parameters. Thus, I think spawn is the right function for me. However that functions returns Tid and not a Thread object. So I want to know how can I make a Thread object out of it. What I would like to achieve is to wait for spawned thread to finish its execution, that is join with main thread.You don't need a Thread object to wait for a thread to finish. One option is to wait for a specific message: import std.concurrency; struct Done {} void func(int i) { ownerTid.send(Done()); } void main() { spawn(&func, 42); receiveOnly!Done(); // <-- Waiting for the Done message } Another option is to wait for all child threads by thread_joinAll(): import core.thread; // ... thread_joinAll(); The reason I suggest the above is because I don't know the answer to your question. :) Ali
Nov 01 2014
Note that thread_joinAll is called automatically when main exits, so if you just want to be sure that your spawned thread completes you don't have to do anything at all. The decision to obscure the Thread object in std.concurrency was deliberate, as it allows us to use more than just kernel threads for concurrency. The thread may even live in another process and the message sent via IPC. If you want to start an asynchronous task and wait for it to complete I suggest the method Ali outlines above. You can also create a Thread directly. What we should really have for this sort of thing is futures, but they don't exist yet. std.parallelism might be worth a look as well, since it has a task queue.
Nov 01 2014
On 11/01/2014 11:13 PM, Sean Kelly wrote:Note that thread_joinAll is called automatically when main exitsHas that always been the case? I remember having to inject thread_joinAll() calls at the ends of the main()s of a couple of examples because of having trouble otherwise. Can I safely remove thread_joinAll()s if they are the last lines in main()? Ali
Nov 01 2014
On Sunday, 2 November 2014 at 06:23:38 UTC, Ali Çehreli wrote:On 11/01/2014 11:13 PM, Sean Kelly wrote:It has always been the case. In fact, I have a comment in the body of Thread.start() explaining this potential race and explaining the need for certain operations in that function. So if there is a race, it isn't meant to be here and should be fixed. I also just filed: https://issues.dlang.org/show_bug.cgi?id=13672 so some attention needs to be paid to this function anyway.Note that thread_joinAll is called automatically when mainexits Has that always been the case? I remember having to inject thread_joinAll() calls at the ends of the main()s of a couple of examples because of having trouble otherwise. Can I safely remove thread_joinAll()s if they are the last lines in main()?
Nov 02 2014
On 11/02/2014 09:04 AM, Sean Kelly wrote:On Sunday, 2 November 2014 at 06:23:38 UTC, Ali Çehreli wrote:I've grepped for thread_joinAll calls in my examples and identified two cases where I needed it at the end of main, both of which about the need to "pull" thread_joinAll inside main's scope. Otherwise, the automatic thread_joinAll call would happen after main's scope ends and it would be too late in the following cases. 1) A scope(exit) should not unregister() before all threads finish. 2) A thread still uses an object tied to main's scope. void main() { auto first = spawn(&player, "second"); register("first", first); scope(exit) unregister("first"); // <-- (1) // ... immutable(int) i = 42; spawn(&worker, &i); // <-- (2) // ... thread_joinAll(); // <-- justified } The thread_joinAll() at the end of main() above is justified to take care of both of those cases. AliCan I safely remove thread_joinAll()s if they are the last lines in main()?It has always been the case. In fact, I have a comment in the body of Thread.start() explaining this potential race and explaining the need for certain operations in that function.
Nov 02 2014
For those cases you could use spawnLinked and then receive LinkTerminated as well, if you're looking for a solution within the concurrency API.
Nov 02 2014
Note that thread_joinAll is called automatically when main exits, so if you just want to be sure that your spawned thread completes you don't have to do anything at all. The decision to obscure the Thread object in std.concurrency was deliberate, as it allows us to use more than just kernel threads for concurrency. The thread may even live in another process and the message sent via IPC. If you want to start an asynchronous task and wait for it to complete I suggest the method Ali outlines above. You can also create a Thread directly. What we should really have for this sort of thing is futures, but they don't exist yet. std.parallelism might be worth a look as well, since it has a task queue.
Nov 01 2014
On Sat, 2014-11-01 at 23:32 +0000, Neven via Digitalmars-d-learn wrote:Ok, a newbie question ahead. I want to create new thread which=20 calls given function with some parameters. Thus, I think spawn is=20 the right function for me. However that functions returns Tid and=20 not a Thread object. =20 So I want to know how can I make a Thread object out of it. What=20 I would like to achieve is to wait for spawned thread to finish=20 its execution, that is join with main thread.Modern thinking is that threads are managed infrastructure that application code should never manage explicitly. In this way of thinking application code only cares about data readiness and/or message passing. With this mind set, using D, you spawn a task and get a Tid in response. The Tid allows you to send messages to the asynchronous activity and to receive messages from it. This is all very, very close to actors. Underneath the actors, there are threads, but your code doesn't care, they are managed resource. All you code cares about is sending messages between asynchronous tasks. As an example of spawning a function and waiting for it to complete using spawn you might look at:=20 https://github.com/russel/Pi_Quadrature/blob/master/D/pi_spawn.d --=20 Russel. =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D Dr Russel Winder t: +44 20 7585 2200 voip: sip:russel.winder ekiga.n= et 41 Buckmaster Road m: +44 7770 465 077 xmpp: russel winder.org.uk London SW11 1EN, UK w: www.russel.org.uk skype: russel_winder
Nov 02 2014