Suliman
Suliman

Reputation: 1499

multithreading in D with for loop

I know that Rust can run loops with lightweight threads. Something like:

use task::spawn;

fn main() {
  for 100.times {
    do spawn {
      io::println("Hello");
    }
  }

How I can do this in D?

Upvotes: 6

Views: 1470

Answers (2)

beatgammit
beatgammit

Reputation: 20205

Relevant API doc: std.parallelism

Here are a few of ways of accomplishing your example:

Parallel foreach, using a TaskPool's parallel:

foreach (i, val; taskPool.parallel(new int[50])) {
    writeln("Hello:", i);
}

Regular foreach, adding tasks to a task pool using put:

foreach (i; 0 .. 50) {
    auto t = task!writeln("Hello:", i);
    taskPool.put(t);
}

Execute each task in a new thread instead of a TaskPool:

foreach (i; 0 .. 50) {
    auto t = task!writeln("Hello:", i);
    t.executeInNewThread();
}

Rust's runtime has a built-in task scheduler, but with D, this is implemented as a library. That being said, the second is the closest in terms of functionality, and the last is the closest in terms of syntax (but they're OS threads, not lightweight).

In D, lightweight threads are explicitly controlled by the programmer. A TaskPool is analogous to the scheduler in Rust/Go, but it gives more fine-grained control to the programmer. This makes it slightly more verbose, but it also gives you parallel versions of map, reduce, foreach, etc. This makes it easier to represent more complex algorithms efficiently.

Running each example should give you the expected result: out of order writes.

Note:

From the doc:

The worker threads in this pool are daemon threads, meaning that it is not necessary to call TaskPool.stop or TaskPool.finish before terminating the main thread.

The second example doesn't wait until all workers are done, so in testing you may get no results (when main finishes, all remaining tasks are killed). You may need to block by calling finish:

taskPool.finish(true);

Upvotes: 11

Vladimir Panteleev
Vladimir Panteleev

Reputation: 25187

D has no built-in abstractions for lightweight threads. Instead, you can:

  • use threads (see std.concurrency and std.parallelism)
  • use fibers, and multitask manually by explicitly yielding execution
  • use a library such as Vibe.d, which implements asynchronous I/O using fibers and implicit yielding on blocking operations

Upvotes: 8

Related Questions