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: about 30ms, not 60
}proc note(text: Str): void {
hive.task.sleep(20)
echo text
}
proc main(): void {
async note("from another thread")
echo "main carries on"
hive.task.sleep(50) // without this, main would return first
} // and take the other thread with itEvery call waits for its callee by default — there is no async func and no future type. What a call means is decided where it is written:
f(x) waits for it.async f(x), as a statement, starts it on a thread of its own and carries on without it.x := async f(x) starts it too, and waits only where x is read — the first read waits, and every later one is free. A binding nobody reads still runs.Whichever starts it, a thread is handed a copy of every argument, worked out on the caller's side first — so async save(build()) runs build() before it carries on, and nothing the caller does afterwards can change what the thread was given. async is only a statement or the value of a declaration; the binding cannot be mut, and what it starts has to be a call to a callable of your own or of the library — not a builtin, a constructor or a partial application, which do no work worth a thread. A call that answers with nothing cannot be bound this way, since there would be nothing for the name to hold.
A panic on a thread started with a binding is raised where the binding is read; one on a thread nobody waits for stops the whole program. When main returns, the program ends, and any thread still running ends with it — except that a program with a window open waits for its windows. hive.task.sleep(ms) parks only the calling thread, and hive.task.sleepForever() parks it for good.