Even better with structured concurrency and no function coloring like Verse:
count := AtomicU32.new(0)
spawn {
loop {
input := try race {
sock.receive()
console.receive()
}
handle_packet(input)
count += 1
} match {
Error e -> log.error(e, "main loop failed")
nil -> log.info(fmt"Finished with {count} requests")
}
}
The receive functions are async so they can only be used inside an async context, like the one created by race. Race is a keyword from Verse that returns the result of the first finished task and cancels the other.