www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - spawn and wait

reply "Puming" <zhaopuming gmail.com> writes:
Hi,

I want to spawn several similar tasks and then wait for all of 
them to complete to go on do some other things, like:

```d
void task(int id)
{
   // do the stuff
}

void main()
{
   foreach (i; 0..10) {
     spawn(&task, i);
   }
   wait(?); // wait for all task to complete
   doSomeOtherThings();
}
```

But I don't see a `wait` method for Tid, similar to Pid in 
std.process.

What is the idiomatic way to do these things?

My current workaround is using messages:

```d
#!/usr/bin/rdmd
import std.stdio;
import std.concurrency;

void child(int id)
{
	writeln("Starting child: ", id);
	ownerTid.send(id);
}

void main()
{
	foreach (i; 0..10)
	{
		spawn(&child, i);
	}
	for (int n = 0; n < 10; ++n) {
		receive((int i) {
			writeln("Received:", i);
		});
	}
}
```

But it is verbose and seems error prone.
Jul 02 2014
next sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 07/02/2014 08:29 PM, Puming wrote:

 I want to spawn several similar tasks and then wait for all of them to
 complete to go on do some other things
If you don't care about account for each of them individually, core.thread.thread_joinAll would work. The following program starts two waves of threads and waits for both of the waves to complete: import std.stdio; import std.concurrency; import core.thread; void foo(Duration duration) { writefln("Working for %s", duration); Thread.sleep(duration); } void spawnThreads(size_t count) { foreach (i; 0 .. count) { spawn(&foo, (i + 1).seconds); } writefln("Started %s workers", count); } void main() { spawnThreads(2); writefln("Waiting for all to finish"); thread_joinAll(); spawnThreads(3); writefln("Waiting for all to finish"); thread_joinAll(); } Ali
Jul 02 2014
next sibling parent reply "Bienlein" <jeti789 web.de> writes:
There is also a Semaphore and Barrier class:

http://dlang.org/phobos/core_sync_barrier.html
http://dlang.org/phobos/core_sync_semaphore.html
Jul 03 2014
parent "Sean Kelly" <sean invisibleduck.org> writes:
On Thursday, 3 July 2014 at 10:25:41 UTC, Bienlein wrote:
 There is also a Semaphore and Barrier class:

 http://dlang.org/phobos/core_sync_barrier.html
 http://dlang.org/phobos/core_sync_semaphore.html
This is probably what I'd do, though both this and thread_joinAll will only work if you have one kernel thread per spawn. If you're using a fiber-based Scheduler, this won't work as expected. In that case you might want to use spawnLinked and trap the LinkTerminated messages or something like that.
Jul 03 2014
prev sibling parent "Puming" <zhaopuming gmail.com> writes:
On Thursday, 3 July 2014 at 04:51:07 UTC, Ali Çehreli wrote:
 On 07/02/2014 08:29 PM, Puming wrote:

 I want to spawn several similar tasks and then wait for all
of them to
 complete to go on do some other things
If you don't care about account for each of them individually, core.thread.thread_joinAll would work. The following program starts two waves of threads and waits for both of the waves to complete: import std.stdio; import std.concurrency; import core.thread; void foo(Duration duration) { writefln("Working for %s", duration); Thread.sleep(duration); } void spawnThreads(size_t count) { foreach (i; 0 .. count) { spawn(&foo, (i + 1).seconds); } writefln("Started %s workers", count); } void main() { spawnThreads(2); writefln("Waiting for all to finish"); thread_joinAll(); spawnThreads(3); writefln("Waiting for all to finish"); thread_joinAll(); } Ali
Thanks that is what I'm looking for
Jul 03 2014
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 07/02/2014 08:29 PM, Puming wrote:

 I want to spawn several similar tasks and then wait for all of them to
 complete to go on do some other things, like:
[...]
 My current workaround is using messages:
I forgot to mention that if message passing is merely a "workaround" :) in this case then perhaps std.parallelism is more suitable. For example, your code may be as simple as running a loop in .parallel in a foreach loop. The foreach loop would not advance until all of the parallel tasks have been completed: import std.stdio; import std.parallelism; import std.range; void task(size_t id) { writefln("Working for %s", id); } void main() { foreach (id; iota(10).parallel) { task(id); } writeln("All done"); } Ali
Jul 03 2014