LEVIATHAN v962456e · 962456eee1

Standard Library

class Worker<T>

The handle to a value that another worker is computing.

since 0.1.0-alpha.1linux

bases
Promise<T>

Overview

A Worker<T> is a Promise<T>, so await worker is the join: it waits for the result, rethrows the worker's failure if there was one, and gives the value. Create one with spawn. Everything that crosses between the program and a worker is copied: the worker works on a snapshot of what its body captured when spawn was called, and its result is copied back at the join, so the two sides never share mutable data. A Worker or Promise handle cannot itself be passed to another worker; use a Channel to exchange values.

On Linux a worker runs on its own operating-system thread. Print results from the code that awaits the worker, not from inside its body, so the output order does not depend on thread timing.

Description

std::spawn(body) starts body as a worker and returns a Worker<T>. Worker<T> extends Promise<T>, so everything you can do with a promise you can do with a worker: await it, isReady(), get() once ready. Joining a worker is an ordinary await.

Joining a worker, and its failure

Worker<int> bad = std::spawn(() => {
    throw RuntimeException("worker failed");
    return 1;
});
try {
    int v = await bad;
    console.writeln("never printed ${v}");
} catch (RuntimeException e) {
    console.writeln("caught: ${e.message}");
}
Worker<string> fine = std::spawn(() => "ok");
console.writeln(await fine);
console.writeln(fine.isReady());
caught: worker failed
ok
true

A worker is not a task of your program: it is a separate thread of execution, and it cannot be cancelled. Use a TaskGroup for cheap, cancellable work on the same thread.

Rules

  • Awaiting a worker whose body threw rethrows a RuntimeException with the original message at the await. Catch it there.
  • The worker's result is copied back to the spawning thread, so what you receive is your own copy.
  • A Worker handle cannot cross a thread boundary. A spawn body must not use another Worker or Promise, whether captured from a local or reached through a global, and sending one through a channel throws an error that says to pass a Channel instead. Join a worker from the thread that spawned it.
  • A worker cannot be cancelled, and a timeout does not stop it: awaitTimeout only stops waiting.
  • Do not print from a worker body; return the data and print after the join.

Examples

See lang.threads for parallel sums and the spawn-time snapshot, and std.Channel for streaming results out of a running worker.

Notes

On the compiled backend a worker is a real thread; the interpreters run workers cooperatively. The results are the same.

Examples

Computing on a worker and joining

int compute() {
    int base = 10;
    Worker<int> w = std::spawn(() => {
        int total = 0;
        for (int i in 1..4) total = total + i * base;
        return total;
    });
    base = 1000;
    return await w;
}
console.writeln(compute());
100

Constructors

new

new()

Create a worker handle that has no body of its own.

The handle is pending until it is resolved or rejected. Programs normally get workers from spawn.

Examples

Worker<string> w = Worker();
w.resolve("settled by hand");
console.writeln(await w);
settled by hand

Fields

failed

bool failed

Whether the worker ended with a failure rather than a value.

failMessage

string failMessage

The message of the failure, or "" when the worker did not fail.

Methods

reject

reject(IException e) -> void

Settle the worker with a failure.

The worker becomes ready and its failed flag is set; await on it then throws a RuntimeException carrying the exception's message. spawn calls this itself when a worker body throws.

Parameters

e
The exception whose message the join rethrows.

Examples

Worker<int> w = Worker();
w.reject(RuntimeException("rejected by hand"));
console.writeln(w.failed);
try {
    int r = await w;
} catch (RuntimeException e) {
    console.writeln("caught: ${e.message}");
}
true
caught: rejected by hand

See also

  • spawn — Run a function as a worker and return a handle to its result.
  • Channel — A queue that carries values from one worker to another.
  • Promise — A value that arrives later.
  • TaskGroup — A set of tasks that live and end together.