View source code
Display the source code in std/parallelism.d from which this page was generated on github.
Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using local clone.

std.parallelism.Task/task - multiple declarations

Function task

Creates a Task on the GC heap that calls an alias. This may be executed via Task.executeInNewThread or by submitting to a TaskPool. A globally accessible instance of TaskPool is provided by taskPool.

auto auto task(alias fun, Args...) (
  Args args
);

Returns

A pointer to the Task.

Example

// Read two files into memory at the same time.
import std.file;

void main()
{
    // Create and execute a Task for reading
    // foo.txt.
    auto file1Task = task!read("foo.txt");
    file1Task.executeInNewThread();

    // Read bar.txt in parallel.
    auto file2Data = read("bar.txt");

    // Get the results of reading foo.txt.
    auto file1Data = file1Task.yieldForce;
}
// Sorts an array using a parallel quick sort algorithm.
// The first partition is done serially.  Both recursion
// branches are then executed in parallel.
//
// Timings for sorting an array of 1,000,000 doubles on
// an Athlon 64 X2 dual core machine:
//
// This implementation:               176 milliseconds.
// Equivalent serial implementation:  280 milliseconds
void parallelSort(T)(T[] data)
{
    // Sort small subarrays serially.
    if (data.length < 100)
    {
         std.algorithm.sort(data);
         return;
    }

    // Partition the array.
    swap(data[$ / 2], data[$ - 1]);
    auto pivot = data[$ - 1];
    bool lessThanPivot(T elem) { return elem < pivot; }

    auto greaterEqual = partition!lessThanPivot(data[0..$ - 1]);
    swap(data[$ - greaterEqual.length - 1], data[$ - 1]);

    auto less = data[0..$ - greaterEqual.length - 1];
    greaterEqual = data[$ - greaterEqual.length..$];

    // Execute both recursion branches in parallel.
    auto recurseTask = task!parallelSort(greaterEqual);
    taskPool.put(recurseTask);
    parallelSort(less);
    recurseTask.yieldForce;
}

Function task

Version of task usable from @safe code. Usage mechanics are identical to the non-@safe case, but safety introduces some restrictions:

auto auto task(F, Args...) (
  F fun,
  Args args
) @trusted
if (is(typeof(fun(args))) && isSafeTask!F);

1. fun must be @safe or @trusted.

2. F must not have any unshared aliasing as defined by hasUnsharedAliasing. This means it may not be an unshared delegate or a non-shared class or struct with overloaded opCall. This also precludes accepting template alias parameters.

3. Args must not have unshared aliasing.

4. fun must not return by reference.

5. The return type must not have unshared aliasing unless fun is pure or the Task is executed via executeInNewThread instead of using a TaskPool.

Function task

Creates a Task on the GC heap that calls a function pointer, delegate, or class/struct with overloaded opCall.

auto auto task(F, Args...) (
  F delegateOrFp,
  Args args
)
if (is(typeof(delegateOrFp(args))) && !isSafeTask!F);

Example

// Read two files in at the same time again,
// but this time use a function pointer instead
// of an alias to represent std.file.read.
import std.file;

void main()
{
    // Create and execute a Task for reading
    // foo.txt.
    auto file1Task = task(&read!string, "foo.txt", size_t.max);
    file1Task.executeInNewThread();

    // Read bar.txt in parallel.
    auto file2Data = read("bar.txt");

    // Get the results of reading foo.txt.
    auto file1Data = file1Task.yieldForce;
}

Notes

This function takes a non-scope delegate, meaning it can be used with closures. If you can't allocate a closure due to objects on the stack that have scoped destruction, see scopedTask, which takes a scope delegate.

Struct 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. A call to workForce, yieldForce, or spinForce is used to ensure that the Task has finished executing and to obtain the return value, if any. These functions and done also act as full memory barriers, meaning that any memory writes made in the thread that executed the Task are guaranteed to be visible in the calling thread after one of these functions returns.

struct Task(alias fun, Args...) ;

The task and scopedTask functions can be used to create an instance of this struct. See task for usage examples.

Function results are returned from yieldForce, spinForce and workForce by ref. If fun returns by ref, the reference will point to the returned reference of fun. Otherwise it will point to a field in this struct.

Copying of this struct is disabled, since it would provide no useful semantics. If you want to pass this struct around, you should do so by reference or pointer.

Properties

NameTypeDescription
done[get] boolReturns true if the Task is finished executing.
spinForce[get] Task.ReturnTypeIf the Task isn't started yet, execute it in the current thread. If it's done, return its return value, if any. If it's in progress, busy spin until it's done, then return the return value. If it threw an exception, rethrow that exception.
workForce[get] Task.ReturnTypeIf this Task was not started yet, execute it in the current thread. If it is finished, return its result. If it is in progress, execute any other Task from the TaskPool instance that this Task was submitted to until this one is finished. If it threw an exception, rethrow that exception. If no other tasks are available or this Task was executed using executeInNewThread, wait on a condition variable.
yieldForce[get] Task.ReturnTypeIf the Task isn't started yet, execute it in the current thread. If it's done, return its return value, if any. If it's in progress, wait on a condition variable. If it threw an exception, rethrow that exception.

Methods

NameDescription
executeInNewThread Create a new thread for executing this Task, execute it in the newly created thread, then terminate the thread. This can be used for future/promise parallelism. An explicit priority may be given to the Task. If one is provided, its value is forwarded to core.thread.Thread.priority. See task for usage example.

Aliases

NameDescription
args The arguments the function was called with. Changes to out and ref arguments will be visible here.
ReturnType The return type of the function called by this Task. This can be void.

Bugs

Changes to ref and out arguments are not propagated to the call site, only to args in this struct.

Authors

License

Boost License 1.0