62. Установка таймаутов в Perl 6

В Perl 5 таймауты устанавливали через сигналы (по крайней мере в моей практике, это был самый понятный способ). В Perl 6 для таймаутов можно воспользоваться промисами.

Давайте запустим бесконечный цикл и попытаемся завершить программу через две секунды.

Вот цикл. Время от времени он выводит счетчик на печать.

for 1 .. * {
    .say if $_ %% 100_000;
}

Получив управление, этот цикл его никогда не отдаст. Поэтому, разумеется, таймер надо поставить до того, как мы дойдем до цикла:

Promise.in(2).then({
    exit;
});

for 1 .. * {
    .say if $_ %% 100_000;
}

Метод Promise.in создает промис, который будет сдержан через заданное число секунд. На этот промис мы — с помощью метода then — добавляем другой промис, который будет сразу выполнен по окончанию первого. Тело промиса — вызов exit.

Запускаем и смотрим:

$ time perl6 timeout.pl
100000
200000
300000
. . .
3700000
3800000
3900000

real 0m2.196s
user 0m2.120s
sys 0m0.068s

Программа успела досчитать до четырех миллионов и завершилась через две секунды.

Для сравнения — программа на Perl 5:

use v5.10;

alarm 2;
$SIG{ALRM} = sub {
    exit;
};

for (my $c = 1; ; $c++) {
    say $c unless $c % 1_000_000;
}

(За две секунды она успевает досчитать до 40 миллионов на том же компьютере, но это другая история.)