Curso de Raku / Programación funcional, concurrente, reactiva y web / Programación concurrente / Canales
Recibir más allá del final
¿Qué ocurre si llamas a .receive más veces de las que
hay valores que tomar? La respuesta depende de si el canal se ha
cerrado.
Toma el ejemplo de productor y consumidor de antes: una tarea en segundo plano envía tres valores y cierra el canal. ¿Y si el consumidor pide un cuarto?
my $c = Channel.new;
start {
$c.send($_) for 1..3;
$c.close;
}
say $c.receive; # 1
say $c.receive; # 2
say $c.receive; # 3
say $c.receive; # one receive too manyEn un canal cerrado, un receive de más lanza una excepción
Cerrar no tira los valores que ya están en cola: las tres llamadas a
.receive de arriba siguen devolviendo 1,
2 y 3. Pero una vez que el canal está cerrado
y vacío, ya no puede llegar ningún valor más, así que
en lugar de dejarte esperar para siempre, Raku lanza una excepción:
Cannot receive a message on a closed channelLa excepción es X::Channel::ReceiveOnClosed. Esto es de
ayuda más que un fastidio: le dice al consumidor, sin lugar a dudas, que
ha vaciado el canal. En la práctica evitas encontrártela consumiendo con
.list (que se detiene limpiamente en el cierre) o iterando
solo mientras queden valores, ambas cosas mostradas en la página
anterior.
En un canal abierto, un receive de más se bloquea
Si el productor nunca cierra el canal, .receive no tiene
manera de saber si aún viene otro valor, así que simplemente
espera:
my $c = Channel.new;
$c.send(1);
say $c.receive; # 1
say $c.receive; # waits here — the channel is open but emptyEl programa se queda colgado en el segundo .receive,
porque podría enviarse todavía un valor. Este es el peligro del
que avisaba la página anterior: olvida el .close y una
«espera al valor siguiente» normal se convierte en una espera que no
termina nunca.
Así que los dos desenlaces son opuestos, de una manera útil. Un canal cerrado falla enseguida cuando está vacío: obtienes una excepción que puedes ver y capturar. Un canal abierto sigue esperando, exactamente lo correcto mientras un productor siga trabajando, pero un cuelgue silencioso si el productor se ha parado calladamente sin cerrar. Cerrar el canal es precisamente lo que convierte ese cuelgue silencioso en una señal clara de que el flujo ha terminado.
Práctica
Resuelve 1 cuestionario sobre el contenido de este tema.
Navegación del curso
← Quiz — Cerrar un canal | Quiz — Recibir más allá del final →
💪 O ve directamente a los ejercicios de esta
sección.