Perl-多线程

官方并不推荐使用 threads 模块.

AnyEvent

用于 event-loop 编程.

参考 man AE 以及 perldoc AnyEvent, perldoc AnyEvent::Intro

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

这里的 fh 指 file handle, rread, cb 指 callback.

这里的 AnyEvent->io 表示创建了一个 I/O watcher, 观察 file handle 的变化.

注意这里还没有开启事件循环.

AnyEvent 对象在未被使用时会被 clean up.

排错

在环境变量中加入 AE_STRICT=1 或者引入 use AnyEvent::Strict;

状态变量

条件变量(condition variable)是用于控制和同步异步操作的一种机制.

AnyEvent->condvar 返回的对象创建.

这里需要注意, 在 producer (callback 函数) 中 call send, 在 consumer 中 call recv:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
use AnyEvent;

$| = 1; print "enter your name> ";

my $name;

my $name_ready = AnyEvent->condvar;

my $wait_for_input = AnyEvent->io (
fh => \*STDIN,
poll => "r",
cb => sub {
$name = <STDIN>;
$name_ready->send;
}
);

# do something else here

# now wait until the name is available:
$name_ready->recv;

undef $wait_for_input; # watcher no longer needed

print "your name is $name\n";

$name_ready 执行 send 之前, 都不会执行 $name_ready->recv 之后的代码, 就像是发送信号, 没有接收到信号之前不会向下执行.

也可以 send 一个变量, 用 recv 来接收一个值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use AnyEvent;

$| = 1; print "enter your name> ";

my $name_ready = AnyEvent->condvar;

my $wait_for_input = AnyEvent->io (
fh => \*STDIN, poll => "r",
cb => sub { $name_ready->send (scalar <STDIN>) }
);

# do something else here

# now wait and fetch the name
my $name = $name_ready->recv;

undef $wait_for_input; # watcher no longer needed

print "your name is $name\n";

利用 condition variable 管理循环

如:

1
2
3
4
5
my $quit_program = AnyEvent->condvar;

# create AnyEvent watchers (or not) here

$quit_program->recv;

可以通过调用 $quit_program->send 来退出, 或者不调用 send 让 event loop 保持循环.

保持循环同样可以直接调用 AnyEvent->condvar->recv

Clock 即 timer

通过 AnyEvent->timer 来设置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
use AnyEvent;

my $cv = AnyEvent->condvar;

my $wait_one_and_a_half_seconds = AnyEvent->timer (
after => 1.5, # after how many seconds to invoke the cb?
cb => sub { # the callback to invoke
$cv->send;
},
);

# can do something else here

# now wait till our time has come
$cv->recv;

默认单位是秒.

注意这里 timer 的 callback 函数只会执行一次.

若想重复调用, 则:

1
2
3
4
5
6
7
my $once_per_second = AnyEvent->timer (
after => 0, # first invoke ASAP
interval => 1, # then invoke every second
cb => sub { # the callback to invoke
$cv->send;
},
);

其他 (signal, child, idle watcher)


Perl-多线程
http://example.com/2023/09/16/Perl-多线程/
作者
Jie
发布于
2023年9月16日
许可协议