Курс Raku / Функційне, конкурентне, реактивне та веб-програмування / Конкурентне програмування / Канали
Читання після кінця
Що станеться, якщо викликати .receive більше разів, ніж
є значень, які можна забрати? Відповідь залежить від того, чи канал було
закрито.
Візьмімо приклад «виробник — споживач» із попереднього: фонова задача надсилає три значення й закриває канал. А що, як споживач попросить четверте?
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; # на одне отримання забагатоНа закритому каналі зайве отримання кидає виняток
Закриття не викидає значень, що вже стоять у черзі, — три виклики
.receive вище все одно повертають 1,
2 та 3. Але щойно канал закрито
і він порожній, нових значень уже ніколи не надійде,
тож Raku не дає вам чекати вічно, а натомість підіймає виняток:
Cannot receive a message on a closed channelЦей виняток — X::Channel::ReceiveOnClosed. Це радше
корисно, ніж прикро: він недвозначно повідомляє споживачеві, що той
вичерпав канал. На практиці ви взагалі на нього не натрапляєте,
споживаючи через .list (який чисто зупиняється на закритті)
або зациклюючись лише поки значення залишаються, — обидва способи
показано на попередній сторінці.
На відкритому каналі зайве отримання блокує виконання
Якщо виробник ніколи не закриває каналу, .receive не має
способу дізнатися, чи надійде ще значення, тож він просто
чекає:
my $c = Channel.new;
$c.send(1);
say $c.receive; # 1
say $c.receive; # чекає тут — канал відкритий, але порожнійПрограма зависає на другому .receive, бо значення
може ще бути надіслане. Це та сама небезпека, про яку
попереджала попередня сторінка: забудьте .close — і
звичайне «дочекайся наступного значення» стане очікуванням, що ніколи не
скінчиться.
Отже, ці два наслідки протилежні, і то в корисний спосіб. Закритий канал швидко зазнає невдачі, коли порожній, — ви отримуєте виняток, який видно й можна перехопити. Відкритий канал і далі чекає — саме те, що треба, поки виробник ще працює, але мовчазне зависання, якщо виробник тихенько спинився, не закривши каналу. Закриття каналу — це рівно те, що перетворює це мовчазне зависання на чіткий сигнал про завершення потоку.
Практика
Виконайте 1 тест за змістом цієї теми.
Навігація курсом
← Тест — Закриття каналу | Тест — Читання після кінця →
💪 Або перейдіть одразу до вправ цього розділу.