raku - 每当信号()在反应块顺序依赖?
问题描述
我有一个小程序,它一直运行到收到 SIGINT 或收到来自 stdin 的两行(按两次回车)。反应块逻辑是:
react {
whenever signal(SIGINT) {
say "Got signal";
exit;
}
whenever $*IN.lines.Supply {
say "Got line";
exit if $++ == 1 ;
}
}
程序将按预期在两个输入的行上退出。
然而 CTRL-C 不会做任何事情,除非它后面跟着一行(回车)。
如果我切换任何时候块的顺序,程序会被 SIGINT 中断,但不会在任何时候执行信号块
react {
whenever $*IN.lines.Supply {
say "Got line";
exit if $++ == 1 ;
}
whenever signal(SIGINT) {
say "Got signal";
exit;
}
}
在使用信号子之前是否需要进行一些其他设置?任何时候块的顺序在反应块中重要吗?
更新
所以似乎 lines() 调用阻止了 react 块的执行(感谢@Håkon)。我有点明白。
当与读取套接字的类似代码结构进行比较时,我很困惑。数据的存在(或缺乏)对信号处理程序的执行没有影响,在这个例子中它可以很好地读取行:
my $listener=IO::Socket::Async.listen("0.0.0.0",4432);
react {
whenever $listener {
whenever $_.Supply.lines() {
say "Got line";
}
}
whenever signal(SIGINT) {
say "Got signal";
exit;
}
}
#testing with:
# curl http://localhost:4432
为什么这与我的原始代码如此不同?
解决方案
如果数据源确实以异步方式运行,则顺序无关紧要,不幸的是这里不是这种情况。Supply
a 上的强制Seq
器不会引入任何并发性,并且会立即尝试生成一个值以在 上发出Supply
,这反过来又会阻止读取$*IN
. 因此,第二次订阅没有机会建立;相同的根本问题导致观察到的其他问题。
解决方案是强制阅读发生在“其他地方”。我们可以用 来做到这一点Supply.from-list(...)
,并告诉它我们确实想要使用当前调度程序而不是它的默认值CurrentThreadScheduler
。因此,这表现得如愿:
react {
whenever Supply.from-list($*IN.lines, scheduler => $*SCHEDULER) {
say "Got line";
exit if $++ == 1 ;
}
whenever signal(SIGINT) {
say "Got signal";
exit;
}
}
在未来的 Perl 6 版本中,这个区域很可能会有所修改。当前的行为是善意的;设计原则是避免隐式引入并发性,遵循供应是管理固有存在的并发性的工具的一般原则,而不是引入它。然而,实际上,这里缺乏并发性可能让更多的人绊倒,而不是帮助。(此外,我们可能会考虑提供真正的非阻塞文件 I/O,而不是从同步文件 I/O + 线程中构建它。)
推荐阅读
- powershell - Get-content 作为变量的输出?
- elasticsearch - 如何编写查询弹性搜索?
- java - 如何通知 FirestorePagingAdapter?
- c# - WPF:SelectionChanged 命令在卸载 UserControl 时触发
- laravel-5 - 在 laravel 中加入表
- c# - 如何让 JSchema 使用 json 数据文件中的 $schema 属性进行验证
- java - java.lang.RuntimeException:Drools 中的意外全局 [map]
- c# - 从 MVC 中的剃刀视图访问模型
- python - 使用循环在路径中的每个文件中执行计算?
- c++ - C++ 创建巨大的向量