是何时反应块顺序中的信号()依赖? [英] is whenever signal() in react block order dependent?

查看:46
本文介绍了是何时反应块顺序中的信号()依赖?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个小程序,它会一直运行到收到 SIGINT 或收到来自 stdin 的两行(按 Enter 两次).反应块逻辑是:

I have a small program which runs until a SIGINT is received or two lines (press enter twice) from stdin are received. The react block logic is:

react {
    whenever signal(SIGINT) {
        say "Got signal";
        exit;
    }
    whenever $*IN.lines.Supply {
        say "Got line";
        exit if $++ == 1 ;
    }
}

程序将按预期在输入的两行退出.

Program will exit on two entered lines as expected.

然而 CTRL-C 不会做任何事情,除非它后面跟着一行(回车).

However CTRL-C will not do anything, unless it is followed by a line (enter).

如果我切换when块的顺序,程序会被SIGINT中断,但不会在when块中执行信号

If I switch the order of the whenever blocks, the program is interrupted by a SIGINT but doesn't execute the signal whenever block

react {
    whenever $*IN.lines.Supply {
        say "Got line";
        exit if $++ == 1 ;
    }
    whenever signal(SIGINT) {
        say "Got signal";
        exit;
    }
}

在使用信号子之前是否需要一些其他设置?在反应块中,every 块的顺序重要吗?

Is there some other setup required before using the signal sub? Is the order of whenever blocks important in a react block?

更新

所以似乎lines() 调用阻止了react 块的执行(感谢@Håkon).我有点明白了.

So it seems the lines() call is blocking the react block from executing (thanks @Håkon). I kind of get it.

当与用于读取套接字的类似代码结构进行比较时,我很困惑.数据的存在(或缺乏)对信号处理程序的执行没有影响,在这个例子中它可以很好地读取行:

When comparing to a similar code structure for reading a socket I'm confused though. The presence of data (or lack of) has no effect on the signal handler executing and it can read lines just fine in this example:

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

为什么这与我的原始代码表现如此不同?

Why does this behave so different to my original code?

推荐答案

顺序无关紧要只要数据源真正以异步方式运行,不幸的是这里并非如此.Seq 上的 Supply coercer 不会引入任何并发性,并且会立即尝试生成一个值以在 Supply 上发出,然后阻止从 $*IN 读取.因此,第二个订阅没有机会被设置;相同的潜在问题会导致观察到的其他问题.

The order doesn't matter provided the data sources really behave in an asynchronous manner, which unfortunately is not the case here. The Supply coercer on a Seq does not introduce any concurrency, and does immediately try to produce a value to emit on the Supply, which in turn blocks on reading from $*IN. Thus, the second subscription doesn't have chance to be set up; the same underlying issue causes the other problems observed.

解决方案是强制读取发生在其他地方".我们可以使用 Supply.from-list(...) 做到这一点,并告诉它我们确实想要使用当前调度程序而不是其默认的 CurrentThreadScheduler.因此,这符合预期:

The solution is to force the reading to happen "elsewhere". We can do that with Supply.from-list(...), plus telling it we really do want to use the current scheduler rather than its default CurrentThreadScheduler. Thus, this behaves as wanted:

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 + 线程构建它.)

It's likely this area will be revised somewhat in future Perl 6 versions. The current behavior was well-intended; the design principle was to avoid implicit introduction of concurrency, following the general principle that supplies are a tool for managing concurrency that inherently exists, rather than for introducing it. However, in reality, the lack of concurrency here has probably tripped up more folks than it has helped. (Further, we may look into offering real non-blocking file I/O, rather than building it from sync file I/O + threads.)

这篇关于是何时反应块顺序中的信号()依赖?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆