Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > weaken


Автор: gcc 25.3.2009, 17:55
видел несколько частей кода с применением Scalar::Util, там дополнительный возможности работы с хэшами массива и т.д.

не понимаю где надо применять этот weaken  какой смысл от них, то есть это цыклическая ссылка, но как она передается? там можно прицепить любой метод при наследовании наверное?

хочется, узнать зачем это - может пригодиться...

Код

$main->{obj1} = MainClass::SubClass1->new($main);
# в методе new MainClass::SubClass1
package MainClass::SubClass1;
use Scalar::Util;
sub new {
    $class = shift;
    bless $self, $class;
    $self->{'main'} = shift;
    Scalar::Util::weaken( $self->{'main'} )
        if ref $self->{'main'};    # weaken circular reference
    $self->{'ua'} = MainClass::Uni::LWP->new($self->{'main'}->{myconst});
}



Код

sub comment : Path {
    my ( $self, $c ) = @_;
 
    eval {
        $self->find_by_uri_path($c);
    };
    
    $c->detach('/not_found')
      if $@ ||
         !defined $c->stash->{comment} ||
         !blessed $c->stash->{comment} ||
         !$c->stash->{comment}->isa('Angerwhale::Content::Item');


Код

sub _on_same_day {
    my ( $a, $b ) = @_;
 
    return 0 if !blessed($a) || !blessed($b);
 
    my @a = ( localtime( $a->creation_time ) )[ 3, 4, 5 ];
    my @b = ( localtime( $b->creation_time ) )[ 3, 4, 5 ];
 
    return ( $a[0] == $b[0] )
      && ( $a[1] == $b[1] )
      && ( $a[2] == $b[2] );
}
 



Автор: ginnie 26.3.2009, 12:43
gcc, предположим у тебя есть объект UsersGroup у него есть свойство users, в котором хранится массив ссылок на объекты User. В объекте User есть поле group, в котором хранится ссылка на объект UsersGroup. Т.е. получаем взаимные ссылки, которые не позволять освободить память, занятую объектами после удаления всех остальных ссылок на них (дестукторы объектов помочь не могут, т.к. они не вызываются). В подобных случаях помогают "слабые" ссылки. В нашем случае мы сделаем слабой ссылку на объект UsersGroup в объекте User. При создании слабой ссылки счетчик ссылок у объекта User не увеличивается. Это приводит к тому, что при удалении всех остальных ссылок, кроме слабой объект уничтожается. Это нужно иметь ввиду при выборе кандидата на слабую ссылку. 

Автор: gcc 26.3.2009, 12:59
Цитата(ginnie @ 26.3.2009,  12:43)
При создании слабой ссылки счетчик ссылок у объекта User не увеличивается. Это приводит к тому, что при удалении всех остальных ссылок, кроме слабой объект уничтожается. Это нужно иметь ввиду при выборе кандидата на слабую ссылку.

понял, мне показалось что это что-то другое

А если сделать копию объекта UsersGroup и название его по другому, или что-то примерно этого, то тогда можно и не использовать weaken... наверное, попробую тогда когда будет такая задача


Автор: ginnie 26.3.2009, 13:23
Приведу пример:

Код

#!/usr/bin/perl

use strict;
use warnings;

use Scalar::Util;

use Devel::Leak::Object qw(GLOBAL_bless);

my $group = UsersGroup->new();
$group->add_user(User->new());

print $group->get_users()->[0]->get_group()->get_name(), $/;
undef $group;

package UsersGroup;

sub new {
    my $class = shift;
    return bless { name => 'Test', users => [] }, $class;
}

sub add_user {
    my ($self, $user) = @_;
    push(@{$self->{users}}, $user);
#    Scalar::Util::weaken($self->{users}->[-1]); # делаем ссылку слабой
    $user->set_group($self);
    return 1;
}

sub get_name {
    return shift->{name};
}

sub get_users {
    return shift->{users};
}

package User;

sub new {
    my $class = shift;
    return bless { group => undef }, $class;
}

sub set_group {
    my ($self, $group) = @_;
    $self->{group} = $group;
#    Scalar::Util::weaken($self->{group}); # делаем ссылку слабой
    return 1;
}

sub get_group {
    return shift->{group};
}


В примере я использую модуль Devel::Leak::Object, который показывает объекты, остающиеся после автоматической "сборки мусора" интерпретатором.
Без использования слабой ссылки мы получаем

Код

Test
Tracked objects by class:
User                                     1
UsersGroup                               1


т.е. в памяти осталось два объекта: один класса UsersGroup, второй - User.

После раскомментирования строки создания слабой ссылки в классе User получаем:

Код

Test
Tracked objects by class:


т.е. никаких объектов в памяти не остается.

Если же мы сделаем слабой ссылку на объект User в классе UsersGroup, то получим

Код

Can't call method "get_group" on an undefined value at weaken_test.pl line 13.
Tracked objects by class:


т.к. никаких ссылок, кроме слабой на объект User нет, он уничтожается сразу после создания слабой ссылки, о чем свидетельствует сообщение об ошибке.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)