【问题标题】:How, in Perl, can I watch for file changes, without polling but with timeout?在 Perl 中,如何在没有轮询但有超时的情况下监视文件更改?
【发布时间】:2021-07-03 13:56:53
【问题描述】:

我正在使用File::ChangeNotify,它允许 (a) 非阻塞检查更改,或 (b) 阻塞等待更改。我真正想要的是介于两者之间的东西:阻塞并等待更改,但在指定的超时后返回。我不想投票,也不能永远阻止。

如果$watcher->wait_for_events 方法有这样的超时参数就好了,但似乎没有;也许实现跨平台太难了。有什么建议吗?

【问题讨论】:

    标签: perl timeout cross-platform blocking polling


    【解决方案1】:

    处理超时的简单方法是alarm 函数。像这样的:

    my $timeout = 10;
    eval {
        local $SIG{ALRM} = sub { die "alarm\n" };
        alarm $timeout;
        $watcher->wait_for_events;
        alarm 0;
    };
    if ($@) {
        die unless $@ eq "alarm\n";   # propagate unexpected errors
        # timed out handling here
    }
    

    【讨论】:

    • 并不是说这是特定于 unix 的,而 File::ChangeNotify 是可移植的。未知的是 OP 和未来读者的要求。
    【解决方案2】:

    你可以把它放到 Perl 可以找到的地方,File::ChangeNotify 会捡起它并使用它。

    package File::ChangeNotify::Watcher::WithTimeOut;
    
    use strict;
    use warnings;
    
    use namespace::autoclean;
    
    use Time::HiRes qw( sleep );
    
    use Moo;
    
    has watcher      => ( is => 'rw' );
    has sleep_cycles => ( is => 'rw' );
    has timeout      => ( is => 'rw' );
    
    sub BUILD 
    {
        my ($self, $args) = @_;
        $self->sleep_cycles( delete $args->{sleep_cycles} );
        $self->timeout( delete $args->{timeout} || 0 );
        $self->watcher( File::ChangeNotify::Watcher::Default->new( %$args ) );
    }
    
    sub wait_for_events 
    {
        my $self   = shift;
    
        my $cycles  = $self->sleep_cycles || -1;
        my $timeout = $self->timeout + time; 
    
        while ( $cycles-- != 0 ) 
        {
            my @events = $self->watcher->_interesting_events;
    
            return @events if @events;
            return @events if $self->timeout && time >= $timeout;
    
            sleep $self->watcher->sleep_interval;
        }
    }
    
    __PACKAGE__->meta->make_immutable;
    
    1;
    

    然后您可以指定timeoutsleep_cycles 参数,当timeout 过期或观察者已睡sleep_cyclessleep_interval 秒时,这些参数将控制权返回给调用者。

    use lib qw(./lib);
    use File::ChangeNotify;
    use Data::Dumper;
    
    my $watcher = File::ChangeNotify->instantiate_watcher ( 
        directories => [ 'C:/Users/holli/testnotify' ],
        filter         => qr/\.(?:pm|conf|yml)$/,
        sleep_interval => 1,
    #    sleep_cycles   => 10,
        timeout        => 5,
    );
    
    while ( 1 ) 
    { 
        my @events = $watcher->wait_for_events;
        print Dumper( \@events );
    }
    

    【讨论】:

    • 这至少对 OP 没有帮助。为此,为了帮助 OP,需要一个模块来提供一种异步检查文件更改的机制。它也需要是可取消的。但如果存在这样的模块,OP 可以直接使用它。
    • @ikegami 现在有一个模块 =)
    • 好多了。 OP 说“我不想投票”,但我相信这只是将对象而不是系统极化。它应该更便宜,尽管它缺乏投票的响应能力。
    • 好吧,如果 OP 不想轮询,那么他们必须一起使用另一个模块。默认观察者做同样的事情: while (1) { 检查更新;睡觉}
    猜你喜欢
    • 2011-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    • 2012-10-05
    • 1970-01-01
    • 2012-04-15
    相关资源
    最近更新 更多