Slide 17 of 37

Concurrency

Starting work and waiting for it
proc slow(label: Str, ms: Int): Str {
	hive.task.sleep(ms)
	return label
}

proc main(): void {
	a := async slow("a", 30)      // starts now
	b := async slow("b", 30)      // starts now, alongside
	echo "{a} and {b}"             // waits for both, right here
}
Bounding a wait
proc slow(label: Str, ms: Int): Str {
	hive.task.sleep(ms)
	return label
}

proc main(): void {
	if slow("c", 300) with timeout 50 is Result.Error(err) {
		echo "gave up after {err.waited}ms"
	}
}
Every call blocks its caller by default — there is no async func, no Future. What a call means is decided where it is written: f(x) waits; async f(x) fires and forgets; x := async f(x) starts it and waits only when x is read; await [f(a), f(b)] starts every call on its own thread and is one barrier resolving to a fully-typed vector. hive.task.sleep(ms) parks only the calling thread, which is why two sleeps started together finish in about the longer one rather than the sum. Any wait can be bounded with `with timeout <ms>`, turning the result into a Result rather than a crash.