Slide 36 of 74

Concurrency: await

Many at once, as a value
proc slow(label: Str, ms: Int): Str {
	hive.task.sleep(ms)
	return label
}

proc main(): void {
	both := await [slow("a", 40), slow("b", 40)]   // one barrier, a Str[2]
	echo both
	echo both[1]                                    // a static length: no guard
}
Many at once, as a statement
proc note(text: Str): void {
	hive.task.sleep(20)
	echo text
}

proc main(): void {
	// Nothing to resolve to, so it is a statement: a batch of side effects
	// finished before the next line, each on its own thread.
	await [note("first"), note("second")]
	echo "both notes are in"
}

await [f(a), g(b)] starts every call in its list on a thread of its own and waits for all of them, as one barrier. It is the only await there is:

  • Every entry has to be a call; a value already in hand has nothing to wait for.
  • The calls answer with one type, since the barrier resolves to a vector of them — as long as the list, so its elements are indexed without a guard. Calls that answer differently are given names instead, with x := async f().
  • Over calls that answer with nothing, there is nothing to resolve to, so it is a statement: these, all of them, then carry on.
  • An await of one call is allowed, and await [] is a compile error.

The arguments of each call are copied before its thread starts, exactly as with async, and there is no way to cancel a call once it has started.