Slide 35 de 74

Concorrência: async

Iniciando um trabalho e esperando por ele
proc slow(label: Str, ms: Int): Str {
	hive.task.sleep(ms)
	return label
}

proc main(): void {
	a := async slow("a", 30)      // inicia agora
	b := async slow("b", 30)      // inicia agora, em paralelo
	echo "{a} and {b}"             // espera pelos dois, aqui: uns 30ms, não 60
}
Dispare e esqueça
proc note(text: Str): void {
	hive.task.sleep(20)
	echo text
}

proc main(): void {
	async note("de outra thread")
	echo "main segue em frente"
	hive.task.sleep(50)         // sem isto, main retornaria antes
}                               // e levaria a outra thread junto

Toda chamada espera pelo chamado por padrão — não existe async func nem tipo futuro. O que uma chamada significa é decidido onde ela é escrita:

  • f(x) espera por ela.
  • async f(x), como instrução, a inicia numa thread própria e segue sem ela.
  • x := async f(x) também a inicia, e só espera onde x é lido — a primeira leitura espera, e todas as seguintes são de graça. Uma ligação que ninguém lê ainda roda.

Qualquer que seja a forma que a inicia, uma thread recebe uma cópia de cada argumento, calculada antes do lado de quem chamou — então async save(build()) roda build() antes de seguir, e nada que quem chamou fizer depois pode mudar o que a thread recebeu. async é só uma instrução ou o valor de uma declaração; a ligação não pode ser mut, e o que ela inicia precisa ser uma chamada a um chamável seu ou da biblioteca — não uma função nativa, um construtor ou uma aplicação parcial, que não fazem trabalho que mereça uma thread. Uma chamada que não responde nada não pode ser vinculada assim, já que não haveria nada para o nome guardar.

Um panic numa thread iniciada com uma ligação é levantado onde a ligação é lida; um numa thread que ninguém espera para o programa inteiro. Quando main retorna, o programa termina, e qualquer thread ainda rodando termina junto — exceto que um programa com uma janela aberta espera por suas janelas. hive.task.sleep(ms) estaciona só a thread que chamou, e hive.task.sleepForever() a estaciona para sempre.