[Moscow.pm] weaken with функции

Vladimir Timofeev vovkasm на gmail.com
Вс Фев 27 23:39:29 PST 2011


2011/2/28 Ivan Petrov <i.petro.77.00 на gmail.com>:
>
>> > некий код:
>> >
>> > sub method
>> > {
>> >    my $self = shift;
>> >    ...
>> >    $self->{handle} = AnyEvent::Handle fh => $fh, on_error => sub {
>> > $self->{error} = $! };
>> >    ...
>> > }
>> >
>> > получается что каллбек цепляет ссылку на $self и из за него деструктор
>> > вызван не может быть до тех пор пока handle не уничтожится.
>> > в случае с просто ссылками - понятно: weaken на них. а здесь куда можно
>> > weaken натравить чтобы деструктор у такого объекта работал?
>>
>> После $self = shift; добавить weaken($self);
>
> В этом случае если эта работа делается внутри конструктора, то добавление
> такого weaken приводит к тому что вместо указателя на объект возвращается
> какая-то ахинея.
>
> вот такой тест:
>
> #!/usr/bin/perl
>
> use warnings;
> use strict;
>
> use utf8;
> use open qw(:std :utf8);
>
> package TestW;
> use AnyEvent::Handle;
> use Scalar::Util qw(weaken);
>
>
> sub new {
>     my ($class, $fh) = @_;
>
>     my $self = bless {  } => $class;
> #     weaken $self;
>     $self->{handle} = new AnyEvent::Handle
>         fh => $fh,
>         on_error => sub { $self->{error} = $! };
>     return $self;
> }
>
> package main;
> use Data::Dumper;
>
> my $o = new TestW(\*STDIN);
> print Dumper $o;
>
> печатает на выходе следующее:
>
> $VAR1 = bless( {
>                  'handle' => bless( {
>                                     '_activity' => '1298875336.78856',
>                                     '_ractivity' => '1298875336.78856',
>                                     '_wactivity' => '1298875336.78856',
>                                     'fh' => \*::STDIN,
>                                     'oobinline' => 1,
>                                     'on_error' => sub { "DUMMY" }
>                                   }, 'AnyEvent::Handle' )
>                }, 'TestW' );
>
> теперь если раскоментировать weaken, то объект превратится в простой хеш:
>
> $VAR1 = {
>           'handle' => bless( {
>                              '_activity' => '1298875430.28919',
>                              '_ractivity' => '1298875430.28919',
>                              '_wactivity' => '1298875430.28919',
>                              'fh' => \*::STDIN,
>                              'oobinline' => 1,
>                              'on_error' => sub { "DUMMY" }
>                            }, 'AnyEvent::Handle' )
>         };
>
> и как быть?

Я бы так делал:
sub new {
    my ($class, $fh) = @_;
    my $self = bless( {}, $class);

    my $me = $self;
    weaken $me;

    $self->{handle} = AnyEvent::Handle->new(
        fh => $fh,
        on_error => sub {
          return unless $me;
          $me->{error} = $!
        }
    );

    return $self;
}

Просто когда вы делаете weaken на ссылку на объект, на который ссылок
нет больше, то этот объект естественно уничтожается сразу.

> Perl 5.10.1
>
> --
> Moscow.pm mailing list
> moscow-pm на pm.org | http://moscow.pm.org
>
>



-- 
Vladimir Timofeev <vovkasm на gmail.com>


Подробная информация о списке рассылки Moscow-pm