在EV回调中是否有可能在Perl中制作类似longjump的东西?

时间:2016-06-25 13:19:17

标签: perl anyevent dbd-pg

我试图在异步环境中模拟同步控制流。

目的是支持没有回调或阻止请求的数据库请求。

我正在尝试使用Coro模块,但我想我并不完全理解它。

以下是代码段:

sub execute {
    my ($sth, @vars) = @_;

    my $res   = $sth->SUPER::execute(@vars);
    my $dbh   = $sth->{Database};
    my $async = new Coro::State;
    my $new;
    $new = new Coro::State sub {
        my $w;
        while (!$dbh->pg_ready) {
            $w = AnyEvent->io(
                fh   => $dbh->{pg_socket},
                poll => 'r',
                cb   => sub {
                    if($dbh->pg_ready) {
                        $w = undef;
                        $new->transfer($async);
                    } 
                }
            ) if not $w;
            print "run once before statement: $sth->{Statement}\n";
            EV::run EV::RUN_ONCE;
        }
    };
    $async->transfer($new);
    $res = $dbh->pg_result;
    $res;
}

以下是测试代码:

my $cv = AE::cv;

ok(my $dbh = db_connect(), 'connected');
ok(my $sth = $dbh->prepare('select pg_sleep(2)'), 'prepared');

my $start_time = time;
ok($sth->execute(), 'executed');

my $duration = time - $start_time;
ok(($duration > 1 && $duration < 3), 'slept');
is(ref($dbh), 'DBIx::PgCoroAnyEvent::db', 'dbh class');
is(ref($sth), 'DBIx::PgCoroAnyEvent::st', 'sth class');

my $status   = 0;
my $finished = 0;

for my $t (1 .. 10) {
    $finished += 1 << $t;
}

for my $t (1 .. 10) {

    my $timer;

    $timer = AE::timer 0.01 + $t/100, 0, sub {

        ok(my $dbh = db_connect(), "connected $t");
        ok(my $sth = $dbh->prepare('select pg_sleep(' . $t . ')'), "prepared $t");
        my $start_time = time;
        ok($sth->execute(), "executed $t");

        my $duration = time - $start_time;
        ok(($duration > $t - 1 && $duration < $t + 1), "slept $t");

        print "duration: $t: $duration\n";

        $status += 1 << $t;
        if ($status == $finished) {
            $cv->send;
        }

        undef $timer;
    };
}

$cv->recv;

完整的模块和测试脚本位于DBIx::PgCoroAnyEvent,此处01_sleeps.t

有人可以看看并解释我的错误吗?

1 个答案:

答案 0 :(得分:0)

eval + die是Perl中的典型方法。

eval { some_function( @args ); };
if( $@ ){
    # caught longjmp
}
...
sub some_function {
    ...
    if( some_condition ){
        die "throw longjmp"
    }
    ...
}