加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

AnyEvent 简单介绍和入门

发布时间:2020-12-16 00:37:21 所属栏目:大数据 来源:网络整理
导读:http://www.php-oa.com/2011/03/23/perl-anyevent-ev.html ? 转载本站文章请注明,转载自:扶凯[http://www.php-oa.com] 本文链接: http://www.php-oa.com/2011/03/23/perl-anyevent-ev.html ????? AnyEvent 是一个性能非常好的基于事件驱动的程序,见有人使

http://www.php-oa.com/2011/03/23/perl-anyevent-ev.html



?



转载本站文章请注明,转载自:扶凯[http://www.php-oa.com]



本文链接: http://www.php-oa.com/2011/03/23/perl-anyevent-ev.html



????? AnyEvent 是一个性能非常好的基于事件驱动的程序,见有人使用它来解决 C10k 的问题,象平时我们写的程 序,都是基于过程。我们都是先做完事件1-> 然后做事件2->然后做事件3 .这种方式。但其实事件就完全不一样了,在主流程中你基本见不到主体,程序的动作都是由事件来驱动。比如我们使用的窗口程序。点最大化最小化,都是基于事 件,当接收到了最大化的事件做最大化事件那部分的程序开始运行。不在从头到尾部来执行。所以我们读基于事件的程序,最好是画成思维导图来帮助我们理解。



???? 基于事件的程序常用到的最大好处是用来做异步,例如,我们要下载 100 个文件,下载完后对这些文件进行处理。可能给每个下载和处理的过程写成事件,这些事件可以同步运行。不知大家了解 Perl 中的 select 不,就是等到句柄可以读 or 写的时候,做不同的读 or 写的操作。事件循环也是一样。



在整个 AnyEvent 入门中,我们只要关注二个点就行, WATCHERS(监控者) 和 条件变量。


WATCHERS(监控者)



在 select 中,有个角色叫"监控者",就是 select 函数本身,在 AnyEvent 中不但可以监控 IO 还可以监控别的一些事件。来做不同的处理。


有如下几个基本的"监控者"。


TIMER : 监控时间,到了一定的条件,然后对不同的时间做不同的事件


I/O: 这个是监控到 IO 是否可以读写,然后做相应的事件


IDLE: 空闲时做什么事件


SIGNAL : 监控观查到不同的信息,调用相应的事件


CHILD PROCESS: 对子程序的状态来调用相应的处理事件



TIMER WATCHERS


基本语法



AnyEvent->timer(


??? after?????? => $seconds,??? # 多久之后做相应的操作.


??? interval?? => $seconds,??? # 在上面条件生效后,每格多久进行一次 callback.


??? cb => $cb,??? # cb 是 callback 的简写,所以知道了吧,只要到了前面的条件,就会运行 cb => 指向的函数.


);



使用实例:


下面的例子是,5 秒后,每 2 秒进行一次 callback 中的事件,直到 $w 这个注册的事件被 undef 为止(也就是 $count > 10 次).



#!/usr/bin/perl


use strict;


use AnyEvent;


?


my $cv = AnyEvent->condvar;


?


my $count = 0;


my $w; $w = AnyEvent->timer(


??????? after?????? => 5,


??????? interval => 2,


??????? cb => sub {


??????????? $count++;


??????????? warn "这是第 $count 次调用";


??????????? if ($count >= 10) {


??????????????? undef $w;


??????????? }? ?


??????? }? ?


??????? ); ?


$cv->recv;



?



I/O WATCHERS


基本语法



my $fh = ....;? # 打开一个句柄


?


my $io; $io = AnyEvent->io(


??? fh => $fh,???????? # 上面打开的句柄,也可以是标准输入和输出


??? poll => "w",???? # 这个地方可以选择 r 和 w 来表示读和写的 IO 事件


??? cb => sub {


??????? syswrite( $fh,"写入的内容" );


??????? undef $io;


??? }


);



使用实例:


下面的例子,是使用 io 监控到可以读,就调用 cb 的函数,直接读文件 test.txt,每次一个字节,直到读完这个文件就通过 undef 消掉这个事件.



#!/usr/bin/perl


use strict;


use AnyEvent;


?


my $cv = AnyEvent->condvar;


?


open my $fh,"<test.txt" or die "不能打开文件句柄 $!";


my $io; $io = AnyEvent->io(


??????? fh????? => $fh,


??????? poll??? => "r",


??????? cb????? => sub {


??????????? my $len = sysread( $fh,my $buf,1 );


??????????? if ($len > 0) {


??????????????? print "read '$buf'n";


??????????? }? ?


??????????? else {


??????????????? undef $io;


??????????????? die "读出错: $!";


??????????? }? ?


??????? });


?


$cv->recv;



?



IDLE WATCHERS



基本语法



my $w = AnyEvent->idle (cb => sub { ... });



使用实例:


下面的例子,当整个程序中,没有其它事件在运行时,就会运行 idle 。它就是当其它事件都在等待和空着的时候,所调用的。



#!/usr/bin/perl


use strict;


use AnyEvent;


?


my $cv = AnyEvent->condvar;


?


my $t; $t = AnyEvent->timer(


??????? after?? => 1,?


??????? interval => 1,


??????? cb => sub { print time()."n" }


??????? ); ?


?


my $w; $w = AnyEvent->idle(


??????? cb => sub {


??????????? warn "idle";


??????? #??? undef $w;


??????? }? ?


??????? ); ?


?


$cv->recv;



?



SIGNAL WATCHERS


基本语法如下,就是当接收到 POSIX signal 的时候,运行 callback 中的事件。



my $w = AnyEvent->signal (signal => "TERM",cb => sub { ... });



?



CHILD PROCRSS WATCHERS


基本语法如下



?? # child process exit


?? my $w = AnyEvent->child (pid => $pid,cb => sub {


????? my ($pid,$status) = @_;


????? ...


?? });



?



?


条件变量



这个是AnyEvent 学习上面几种 WATCHERS 后必须要了解的。大家都见到上面有 AnyEvent->condvar; 和 $cv->recv; 吧,这个其实就是条件,当达到什么条件退出事件循环。所以 AnyEvent 中没有传统事件中的 loop 函数。所以使用条件变量来模拟就好了。


基本的 $cv->recv 是和 $cv->send 成对出现的,当事件调用 send 时 recv 收到这个调用,就会退出事件。下面的 $cv->begin 和 $cv->end 也基本是这个意思。send 是单个条件。begin 和 end 是多个条件。



#!/usr/bin/perl


use strict;


use AnyEvent;


?


my $cv = AnyEvent->condvar( cb => sub {


??? warn "调用结束";


});


?


for my $i (1..10) {


??? $cv->begin;


??? my $w; $w = AnyEvent->timer(after => $i,cb => sub {


??????? warn "finished timer $i";


??????? undef $w;


??????? $cv->end;


??? });


}


?


$cv->recv;



默认的 condvar 会对事件建一个条件为假的变量,所以直接有 send 和 begin send 之类才会变成真,然后退出事件循环。可以给这个地方看成一个信号量来理解就好了。y


如果条件不成立,在 AnyEvent 中事件会一直 loop 。所以上面的例子中没有 send 。



?有关 AnyEvent 其它,大家入门后可以玩玩象 AnyEvent::HTTP,twiggy 之类。看看这些应用和项目。



另外,在 AnyEvent 中我们常常使用 EV .他是一个 C 的 libev 的 Perl 接口,有非常高的性能。看完上面,在看看下面 EV 的使用,非常容易吧,基本不变。只是没出现条件变量,


使用的传统的 EV::loop; 来使这个运行起来。



use EV;


?


?? # TIMERS


?


?? my $w = EV::timer 2,sub {


????? warn "is called after 2s";


?? };


?


?? my $w = EV::timer 2,2,sub {


????? warn "is called roughly every 2s (repeat = 2)";


?? };


?


?? undef $w; # destroy event watcher again


?


?? my $w = EV::periodic 0,60,sub {


????? warn "is called every minute,on the minute,exactly";


?? };


?


?? # IO


?


?? my $w = EV::io *STDIN,EV::READ,sub {


????? my ($w,$revents) = @_; # all callbacks receive the watcher and event mask


????? warn "stdin is readable,you entered: ",<STDIN>;


?? };


?


?? # SIGNALS


?


?? my $w = EV::signal 'QUIT',sub {


????? warn "sigquit receivedn";


?? };


?


?? # CHILD/PID STATUS CHANGES


?


?? my $w = EV::child 666,$revents) = @_;


????? my $status = $w->rstatus;


?? };


?


?? # STAT CHANGES


?? my $w = EV::stat "/etc/passwd",10,$revents) = @_;


????? warn $w->path," has changed somehow.n";


?? };


?


?? # MAINLOOP


?? EV::loop;?????????? # loop until EV::unloop is called or all watchers stop


?? EV::loop EV::LOOP_ONESHOT;? # block until at least one event could be handled


?? EV::loop EV::LOOP_NONBLOCK; # try to handle same events,but do not block

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读