如何确保函数在perl中永远不会并发执行?

如何确保函数在perl中永远不会并发执行?,perl,Perl,我使用Mojo::IOLoop与端口通信,以向数字接收器发送命令 因为接收者只能打开端口一次,但与之通信的代码位于web界面和web服务器的后面,因此存在同时发送命令的风险——因此数字接收者会丢失这些命令,从而出现问题 那么,如何确保某些代码永远不会并发运行呢 我试着像这样使用文件锁: sub enqueue { my $self = shift; my ($cmd, $promise) = @_; while (!(flock DATA, LOCK_EX|LOCK_N

我使用Mojo::IOLoop与端口通信,以向数字接收器发送命令

因为接收者只能打开端口一次,但与之通信的代码位于web界面和web服务器的后面,因此存在同时发送命令的风险——因此数字接收者会丢失这些命令,从而出现问题

那么,如何确保某些代码永远不会并发运行呢

我试着像这样使用文件锁:

sub enqueue {
    my $self = shift;
    my ($cmd, $promise) = @_;

    while (!(flock DATA, LOCK_EX|LOCK_NB)) { sleep(0.25) }

    my (@r);

    my $id = Mojo::IOLoop->client({ address => '192.168.1.204', 
                                    port => 23, timeout => 13 }
              => sub ($loop, $err, $stream) {
                  return $promise->reject('could not open stream') unless $stream;

                  $stream->on(error => sub ($stream, $err) {
                                  flock(DATA, LOCK_UN);
                                  $stream->close;
                                  $promise->reject($err);
                              });

                  $stream->on(read => sub ($stream, $bytes) {
                                  $bytes =~ s/\r\n$//;
                                  push @r, split /\r\n/, $bytes;
                                  # stream done is a function that checks that 
                                  # the appropriate number of lines got sent back
                                  if (stream_done(@r)) {
                                      flock(DATA, LOCK_UN);
                                      $promise->resolve(\@r);
                                      $stream->close;
                                  };
                              });

                  $stream->on(timeout => sub ($stream) {
                                  flock(DATA, LOCK_UN);
                                  $stream->close;
                                  $promise->reject('timeout') if ($err);
                              });
                  $stream->write($cmd);
              });
}

我不确定我是否正确理解你想做什么,因为我不熟悉魔咒。但如果您只是不想执行函数两次,请创建一个锁文件,并在完成时删除:

使用File::Slurp;
将我的方法分为只执行一次{
my$tmp='temp.txt';
如果(方法正在运行($tmp)),则返回;
#做你的事
取消$tmp的链接;
}
sub正在运行{
我的($filename)=@;
如果(-e$tmp){
返回1;
}
写_文件($tmp,“running”);
返回0;
}

我会重新设计这个问题,这样就只有一件事可以与接收器对话。web进程只与一个对象通信,因为它是唯一与接收者通信的对象,不需要与任何人协调。例如,想想syslog是如何工作的。@briandfoy-所以我一直在思考这个问题,但却被困在一块岩石和一个坚硬的地方之间。由于从接收器返回响应的方式,我只能通过异步的Mojo::IOLoop使其工作,因此很难避免并发。我还试图用一个队列来做这件事,但完全搞砸了。可能是我的架构出错了——这并不奇怪,因为我不是专业人士,这是我第一次尝试(相对而言)低级别的网络协议