Canais entre fibras
L.canal: o chan do Go dentro de um laço — encontro com capacidade 0, fila com N, e fechar que termina o consumidor.
Duas fibras que dividem uma lista precisam combinar quem mexe quando. O canal é a combinação pronta: uma fibra envia, a outra recebe, e o laço suspende quem precisa esperar. Nada é compartilhado além do próprio canal.
dataforge
adopt Arcane.Laco as L
laco := L.novo()
pedidos := L.canal(2)
log := []
stream action produtor():
cycle i from 1 to 5:
log.append($"envia {i}")
emit L.enviar(pedidos, i) // espera se já há 2 na fila
pedidos.fechar()
stream action consumidor():
caixa := {}
persist yes:
emit L.receber(pedidos, caixa, "v")
given caixa["v"] is void: // fechado e vazio: acabou
halt
log.append($"trata {caixa["v"]}")
emit L.dormir(1) // o consumidor é mais lento
L.fibra(laco, produtor)
L.fibra(laco, consumidor)
L.rodar(laco)
tratados := [x cycle x in log given x.starts_with("trata")]
assert tratados is ["trata 1", "trata 2", "trata 3", "trata 4", "trata 5"]Capacidade decide o ritmo#
| Capacidade | Quem envia | Uso |
|---|---|---|
| 0 (padrão) | espera até alguém receber — um encontro | entregar em mão: sincronizar duas fibras |
| N | segue até haver N esperando | absorver rajadas, sem deixar a fila crescer sem fim |
É a contrapressão de graça: um produtor mais rápido que o consumidor para no enviar, em vez de encher a memória. Com o canal de capacidade 2 acima, o produtor nunca fica mais de três itens à frente.
Fechar#
- Quem produz fecha.
pedidos.fechar()diz "não vem mais nada"; o consumidor recebevoiddepois de esvaziar a fila, e sai do laço. - Enviar num canal fechado é erro — anotado em
L.falhas(laco), e a fibra que enviou termina. Ninguém ia ler. - Receber pela caixa.
emité instrução, e não expressão: o valor volta escrito no vault que a fibra passou. Explícito, e melhor que fingir queemitdevolve algo.