Одна ошибка, которую вы делаете, заключается в том, что вы предполагаете, что расходные материалы потеряют значения, или вы предполагаете, что они прекратят генерировать значения, пока react
заблокирован.
Они не будут.
Они продолжают генерировать значения.
Вы также должны попытаться запустить код в whenever
как можно быстрее.
(Представьте, что это обработчик прерываний процессора.)
Из этого правила могут быть некоторые исключения, особенно для supply
блоков.
Используя предоставленную вами структуру, это один из способов достижения желаемого:
react {
# Are we ignoring the interval(1) values?
my Bool:D $ignore = False;
# The sleeping status of interval(5).
my Promise:D $sleep .= kept;
whenever Supply.interval(1) {
# Skip if it is supposed to be blocked.
next if $ignore;
say DateTime.now.posix;
}
# First one runs immediately, so skip it.
whenever Supply.interval(5).skip {
# Don't run while the “sleep” is pending.
next unless $sleep.status; # Planned
if $ignore {
$ignore = False;
say 'Sleep Done';
} else {
$ignore = True;
# Must be less than the multiple of 5 we want
# otherwise there may be a race condition.
$sleep = Promise.in(9);
}
}
whenever signal(SIGINT) {
say "Done.";
done;
}
}
Это не очень понятно.
Как насчет того, чтобы просто использовать .rotor
, чтобы пропустить каждый третий интервал из 5?
react {
my Bool:D $ignore = True;
# Note that first one runs immediately. (no .skip)
# We also want it to always be a few milliseconds before
# the other Supply, so we put it first.
# (Should have done that with the previous example as well.)
whenever Supply.interval(5).rotor(1, 1 => 1) {
$ignore = !$ignore;
}
whenever Supply.interval(1) {
next if $ignore;
say DateTime.now.posix;
}
whenever signal(SIGINT) {
say "Done.";
done;
}
}
Пока мы занимаемся этим, почему бы не использовать .rotor
в .interval(1)
Supply?
react {
whenever Supply.interval(1).rotor(1 xx 4, 1 => 10) {
say DateTime.now.posix;
}
whenever signal(SIGINT) {
say "Done.";
done;
}
}
Обратите внимание, что мы не можем просто использовать 5 => 10
, потому что это объединяет их, и мы хотим, чтобы они запускались по отдельности.
Обратите внимание, что .grep
также работает с припасами, поэтому мы могли бы использовать его для проверки значения $ignored
.
react {
my Bool:D $ignore = True;
whenever Supply.interval(5).rotor(1, 1 => 1) {
$ignore = !$ignore;
}
whenever Supply.interval(1).grep({ !$ignore }) {
say DateTime.now.posix;
}
whenever signal(SIGINT) {
say "Done.";
done;
}
}