This is an old revision of the document!


Lab 05: Multithreading

Concurrency

Most modern microprocessors consist of more than one core, each of which can operate as an individual processing unit. They can execute different parts of different programs at the same time. The features of the std.parallelism module make it possible for programs to take advantage of all of the cores in order to run faster.

std.parallelism.Task

Operations that are executed in parallel with other operations of a program are called tasks. Tasks are represented by the type std.parallelism.Task.

Task represents the fundamental unit of work. A Task may be executed in parallel with any other Task. Using this struct directly allows future/promise parallelism. In this paradigm, a function (or delegate or other callable) is executed in a thread other than the one it was called from. The calling thread does not block while the function is being executed.

For simplicity, the std.parallelism.task and std.parallelism.scopedTask functions are generally used to create an instance of the Task struct.

Using the Task struct has three steps:

1. First, we need to create a task instance.

int anOperation(string id) {
  writefln("Executing %s", id);
  Thread.sleep(1.seconds);
  return 42;
}
 
void main() {
  /* Construct a task object that will execute
   * anOperation(). The function parameters that are
   * specified here are passed to the task function as its
   * function parameters. */
   auto theTask = task!anOperation("theTask");
   /* the main thread continues to do stuff */
}

2. Now we've just created a new Task instance, but the task isn't running yet. Next we'll launch the task execution.

  /* ... */
  auto theTask = task!anOperation("theTask");
 
  theTask.executeInNewThread(); // start task execution
  /* ... */

3. At this point we are sure that the operation has been started, but it's unsure whether theTask has completed its execution. yieldForce() waits for the task to complete its operations; it returns only when the task has been completed. Its return value is the return value of the task function, i.e. anOperation().

  /* ... */
  immutable taskResult = theTask.yieldForce();
  writefln("All finished; the result is %s\n", taskResult);
  /* ... */

The Task struct has two other methods, workForce and spinForce, that are used to ensure that the Task has finished executing and to obtain the return value, if any. Read their docs and discover the differences in behaviour and when their usage is preferred.

dss/laboratoare/05.1561456732.txt.gz ยท Last modified: 2019/06/25 12:58 by eduard.staniloiu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0