Any event intro
-
Upload
qiang -
Category
Technology
-
view
2.081 -
download
0
description
Transcript of Any event intro
AnyEvent介绍Achilles Xu
11年7月4日星期一
Contents简介
Hello World
Watcher
CondVar
参数传递
工具模块
封装
Bugs
11年7月4日星期一
丫是啥?
一个异步框架,支持多种底层驱动
EV, libevent, POE, Glib, QT, Tk
11年7月4日星期一
Hello Worlduse AnyEvent;
my $cv = AnyEvent->condvar;
my $w = AnyEvent->timer(
'after' => 5,
'cb' => sub {
print "hello world\n";
$cv->send;
}
);
$cv->recv;
11年7月4日星期一
元素介绍watcher
I/O
timer
signal
child process
idle
condvar
工具模块
AnyEvent::Handle
AnyEvent::DNS
AnyEvent::Socket
11年7月4日星期一
I/O Watcher use AnyEvent;
$| = 1; print "enter your name> ";
my $name;
my $wait_for_input = AnyEvent->io ( fh => \*STDIN, # which file handle to check poll => "r", # which event to wait for ("r"ead data) cb => sub { # what callback to execute $name = <STDIN>; # read it } );
# do something else here
11年7月4日星期一
Timer Watcher
my $once_per_second = AnyEvent->timer ( after => 0, # first invoke ASAP interval => 1, # then invoke every second cb => sub { # the callback to invoke print "hi\n"; }, );
11年7月4日星期一
Watcher变量的作用域
Watcher变量超出作用域以后,会被注销
11年7月4日星期一
Watcher变量的作用域use AnyEvent;
sub aaa {
my $w = AnyEvent->Timer(
after => 3,
interval => 5,
cb => sub { print "hello\n"; }
);
}
my $cv = AnyEvent->condvar;
aaa();
$cv->recv; # won't print hello every 5 seconds.11年7月4日星期一
Watcher变量的作用域use AnyEvent;
my $w; # 把Watcher变量存储在外层作用域
sub aaa {
$w = AnyEvent->Timer(
after => 3,
interval => 5,
cb => sub { print "hello\n"; }
);
}
my $cv = AnyEvent->condvar;
aaa();
$cv->recv; # will print hello every 5 seconds.
11年7月4日星期一
Watcher变量的作用域use AnyEvent;
sub aaa {
# 用闭包保存watcher变量
my $w; $w = AnyEvent->Timer(
after => 3,
interval => 5,
cb => sub { print "hello\n"; $w; }
);
}
my $cv = AnyEvent->condvar;
aaa();
$cv->recv; # will print hello every 5 seconds.
11年7月4日星期一
Watcher变量的作用域use AnyEvent;
sub aaa {
my $w; $w = AnyEvent->timer(
after => 5,
cb => sub {
print "hello\n";
undef $w;
});
}
aaa();
AnyEvent->condvar()->recv();
11年7月4日星期一
CondVar
启动main loop,类似POE::Kernal->run();
同步点控制,类似$thread->join();
“This module is an AnyEvent user, you need to make sure that you use and run a supported event loop.”
11年7月4日星期一
CondVaruse AnyEvent;
my $w = AnyEvent->timer(
after => 0,
interval => 5,
cb => sub {
print "hello\n";
}
);
my $cv = AnyEvent->condvar;
$cv->recv; # just like while (1) {...}
11年7月4日星期一
CondVaruse AnyEvent;
use AnyEvent::HTTP;
# 顺序执行一些操作...
my @cvs;
for (1 .. 5) {
my $cv = AnyEvent->condvar; # like thread id
push @cvs, $cv;
http_get("http://some_url", sub {
$cv->send; # like return in thread func
});
}
$_->recv for @cvs; # like $_->join for @threads;
# 继续顺序执行一些操作...
11年7月4日星期一
参数传递
闭包(closure)是唯一方式
PP(Par::Packer)打包时会产生很警告
perl -T
11年7月4日星期一
参数传递
use AnyEvent;
my $x = "Tom";
AnyEvent->timer(afer => 5, cb => sub {
print "hello $x";
}
11年7月4日星期一
工具模块use AnyEvent;
use AnyEvent::Handle; my $cv = AnyEvent->condvar; my $hdl; $hdl = new AnyEvent::Handle fh => \*STDIN, on_error => sub { my ($hdl, $fatal, $msg) = @_; warn "got error $msg\n"; $hdl->destroy; $cv->send; }; # send some request line $hdl->push_write ("getinfo\015\012"); # read the response line $hdl->push_read (line => sub { my ($hdl, $line) = @_; warn "got line <$line>\n"; $cv->send; }); $cv->recv;
11年7月4日星期一
工具模块use AnyEvent;
use AnyEvent::HTTP;
my $cv = AnyEvent->condvar;
http_get("http://www.sina.com.cn", # 不存在watcher作用域问题
sub {
my ($data, $headers) = @_;
print $headers->{Status}, "\n";
print $data, "\n";
$cv->send;
});
$cv->recv;
11年7月4日星期一
工具模块use AnyEvent; # not AE
# file handle or descriptor readable my $w = AE::io $fh, 0, sub { ... };
# one-shot or repeating timers my $w = AE::timer $seconds, 0, sub { ... }; # once my $w = AE::timer $seconds, $interval, sub { ... }; # repeated
print AE::now; # prints current event loop time print AE::time; # think Time::HiRes::time or simply CORE::time. my $cv = AE::cv;
11年7月4日星期一
封装
顺序完成几个步骤,然后调用传入的回调函数
并发做几件事,全部完成后调用传入的回调函数
以上二者结合
状态数据隐藏在封装函数的内部
适用于所有异步消息框架的封装
11年7月4日星期一
封装http_get_retry("http://www.sina.com.cn",
max_retries => 3,
sub {
my ($data, $headers) = @_;
if (defined $data) {
print "load ok";
} else {
print "try 3 times failed";
}
});
11年7月4日星期一
封装http_get_file("http://aaa.com/somefile.tar.gz",
"/data/files/somefile.tar.gz",
max_concurrent => 20,
sub {
my ($data, $headers) = @_;
if (defined $data) {
print "download ok";
} else {
print "some error happens: " . $headers->{Status};
}
});
11年7月4日星期一
封装
http_get( $url, sub { ... });
DNS Resolving
TCP Connecting
Sending Request
Reading Response
11年7月4日星期一
Bugs
多进程侦听socket
accept后使用push_read
rtimeout有时会瞬间出发
驱动:EV、PurePerl
单进程时不会发生
11年7月4日星期一
Bug's Solution
超时回调中做补差timer
*AE::now = sub { return AE::time; }
*AE::now = *AE::time doesn't work
11年7月4日星期一
谢谢
Questions?
11年7月4日星期一