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
RuntimeExceptionwith the original message at theawait. Catch it there. - The worker's result is copied back to the spawning thread, so what you receive is your own copy.
- A
Workerhandle cannot cross a thread boundary. A spawn body must not use anotherWorkerorPromise, whether captured from a local or reached through a global, and sending one through a channel throws an error that says to pass aChannelinstead. Join a worker from the thread that spawned it. - A worker cannot be cancelled, and a timeout does not stop it:
awaitTimeoutonly 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 failedWhether the worker ended with a failure rather than a value.
failMessage
string failMessageThe message of the failure, or "" when the worker did not fail.
Methods
reject
reject(IException e) -> voidSettle 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