Program Structure

Concurrency

Run named tasks with concurrent, choose a timeout result with else, and distinguish an Err value from a runtime fault.

Run independent tasks with concurrent and collect their results in named record fields. Set a timeout and use else to choose the result when time runs out.

Install Topaz with First Program. Save each program below in a working folder and run its commands there.

Complete before the timeout

Save this code as concurrency-success.tpz.

TOPAZ
let result = concurrent(timeout: 3s) {
    total: 1 + 2
    label: "ready"
} else {
    { total: -1, label: "timeout" }
}

print("{result.total} {result.label}")

Check and run it.

BASH
topaz check concurrency-success.tpz
topaz run concurrency-success.tpz

Both commands exit with code 0. When both tasks finish within three seconds, the program prints the result record values.

Output
3 ready

Each named expression inside concurrent is a task, also called an arm. Here, total computes 3 and label produces "ready". Their names become fields in the result record. The record does not indicate which task started or finished first.

Return a different value on timeout

This program has a task that keeps looping. Save it as concurrency-timeout.tpz.

TOPAZ
function spin() -> int {
    let mut i = 0
    while true { i += 1 }
    i
}

let result = concurrent(timeout: 5ms) {
    stuck: spin()
} else {
    { stuck: -1 }
}

print("{result.stuck}")

Check and run it.

BASH
topaz check concurrency-timeout.tpz
topaz run concurrency-timeout.tpz

The five-millisecond timeout selects else, which supplies the whole result. Both commands exit with code 0.

Output
-1

No task results are returned on timeout, including results from tasks that already finished. If your own task should finish, correct its loop condition or input. Returning a timeout value does not fix the unfinished work.

Distinguish completion, timeout, and faults

What happensExpression result
Every task finishes before timeoutA record with one field per task
Time runs out firstThe else block value
A task faults before timeoutThe whole expression faults, without running else

A fault is an error that stops evaluation, such as an out-of-bounds array access. A task returning Err(error) completes with an ordinary Result value. That value goes into its named field. The else block handles timeouts and neither catches faults nor extracts values from Err.

The else result must have a type compatible with the successful result record. Both examples use the same field names and compatible field types on both paths.

Control output order

Print after concurrent returns when output order matters. Task names identify results, but the runtime does not specify task start or completion order. It also does not specify how task output interleaves, how fairly tasks are scheduled, or whether interleaving repeats across runs.

After timeout, the runtime decides how to cancel unfinished work and clean up its resources. Later faults from abandoned work do not reach the Topaz expression. Do not depend on a particular cancellation or cleanup sequence.

Write a valid timeout

Write a whole number followed immediately by ms, s, or m, as in 5ms or 3s. Spaces and property forms such as .seconds are invalid. Duration literals are used in the concurrent timeout clause.

After conversion to milliseconds, the duration must fit unsigned u64, from 0 to 18446744073709551615. Larger values produce TPZ5001. Reduce the literal to a supported value.

UnitLargest accepted literal
Milliseconds18446744073709551615ms
Seconds18446744073709551s
Minutes307445734561825m

Give each task a unique name. A timeout requires else. The form concurrent { ... } waits for all tasks without a timeout and cannot have else. Prefer an explicit timeout for application examples.

Topaz has no implicit async model, async/await, public task handles, or general duration arithmetic. See Runtime Behavior for faults and ordering, and Forbidden & Deferred Forms for unsupported syntax.