AnyEventサンプルその5

AnyEvent::Handleの扱いに苦労した。

ioやtimerのヲチャー変数のようにundefでも行けた。参照カウントが残っているとどうもよくないのかしらね。AnyEvent::JSONRPC::Liteでもweaken $handleとやっている部分がどうも今ひとつ理解できずにいたのだが、大事だよということはよくわかった。

サーバ側
use strict;
use warnings;
use AnyEvent;
use AnyEvent::Handle;
use AnyEvent::Socket;
use Data::Dumper;

tcp_server '127.0.0.1', 8888, sub {
    my ($fh) = @_ or die;
    my $handle = AnyEvent::Handle->new(
        fh       => $fh,
        on_error => sub { shift->destroy; warn "ON_ERROR"; },
        on_eof   => sub { shift->destroy; warn "ON_EOF"; },
    );

    $handle->on_read(
        sub {
            undef $handle;
            warn "ON_READ";
            shift->unshift_read(
                json => sub {
                    my ( $handle, $request ) = @_;
                    $handle->push_write(
                        json => { foo => $request->{foo} . " echo!!" } );
                }
            );

        }
    );
};

sub _time {
    warn AnyEvent->now;
}
AE::cv->recv;
サーバ側(デッドロック?してしまうだめな例)
use strict;
use warnings;
use AnyEvent;
use AnyEvent::Handle;
use AnyEvent::Socket;
use Data::Dumper;

tcp_server '127.0.0.1', 8888, sub {
    my ($fh) = @_ or die;
    my $handle = AnyEvent::Handle->new(
        fh       => $fh,
        on_error => sub { shift->destroy; warn "ON_ERROR"; },
        on_eof   => sub { shift->destroy; warn "ON_EOF"; },
    );
    $handle->on_read(
        sub {
            warn "ON_READ";
            ## ここのundef $handleがないとダメ。
            shift->unshift_read(
                json => sub {
                    my ( $handle, $request ) = @_;
                    $handle->push_write(
                        json => { foo => $request->{foo} . " echo!!" } );
                    warn "WRITE";
                    $handle->destroy;
                }
            );
        }
    );   
};

sub _time {
    warn AnyEvent->now;
}
AE::cv->recv;
クライアント側
use strict;
use warnings;
use AnyEvent;
use AnyEvent::Handle;
use AnyEvent::Socket;
use Data::Dumper;

my $cv = AE::cv;
tcp_connect '127.0.0.1', 8888, sub {    my ($fh) = @_ or die;
    my $handle = AnyEvent::Handle->new(
        fh       => $fh,
        on_error => sub { shift->destroy; warn "ON_ERROR"; },
        on_eof   => sub { shift->destroy; warn "ON_EOF"; },
    );

    $handle->push_write( json => { foo => 'foo' } );

    $handle->push_read(
        json => sub {
            my ( $handle, $result ) = @_;
            $cv->send( $result->{foo} );
        }
    );
};
print $cv->recv;
print "\n";