std.task
Tasks, channels and the scheduler that runs them.
Each thread has a scheduler, written here over the runtime's park and poller, and main runs
as a task of it. The module holds spawn and its Task with its TaskStatus, TaskScope,
spawnDetached, sleep and yieldNow; cancellation through Cancelled and withTimeout; a
panic that ends a task, not the process, described by PanicInfo; and Channel, Select and
Timer, which work within a thread and across threads.
The threads and their pool are std.thread's, the locks std.sync's and the signals std.os's;
they stand on parts kept here, internal to std: the locks' state, the scheduler, launchOn,
the registry of the living schedulers and the natives.
Examples
import std.io { println };
import std.task { spawn, Channel };
fn main(): void throws Error {
let ch = Channel<int>.new();
let producer = spawn(() => {
for (i in 1..=3) {
try ch.send(i * 10);
}
ch.close();
});
var total = 0;
while (let v = try ch.recv()) {
total += v;
}
try producer.await();
println(total);
}
60
Types
yield when close() unwinds its coroutine.Functions
pub fn sleep(d: Duration): void throws Cancelled
Parks the running task until at least d has passed, while the other tasks of its thread run.
A sleep of zero or less lets the tasks that are ready run first.
Errors
Throws Cancelled in a cancelled task; a cancel during the sleep ends it early.
pub fn yieldNow(): void throws Cancelled
Lets the other ready tasks of the thread run first: the running task goes behind them.
Errors
Throws Cancelled in a cancelled task, as every wait does.
pub fn spawn<T, E :: [Error]>(body: fn() -> T throws E): (Task<T> throws E)
Starts body as a task of the running thread and returns its handle.
The task runs once the tasks ready before it had their turn, and Task.await on the handle
gives its value or throws its error — E, what the body throws, the handle's type carries. The
handle is the only way to that error, so a call that drops it warns; spawnDetached is the
task nobody awaits, and TaskScope.spawn one the scope's close() waits for.
pub fn withTimeout<T, E :: [Error]>(
d: Duration,
body: fn() -> T throws E
): T throws [E, TimedOut, Cancelled]
Runs body as a task of its own and returns what it returns, unless d passes first.
When d passes first, the body is cancelled, and TimedOut is thrown once it has ended. A
cancel of the caller cancels the body too; whenever this returns, the body has ended.
Errors
Throws the body's own errors as they are; TimedOut when d passed before the body ended;
Cancelled when the caller was cancelled.
pub fn spawnDetached(body: fn() -> void throws Cancelled): void
Starts body as a task of the running thread, with no handle.
It runs once the tasks ready before it had their turn, and nobody waits for it — the program
ends with main, done or not. Only a cancellation may end it early: it handles every other
error itself.