nothing94 has asked for the wisdom of the Perl Monks concerning the following question:

With this SIMPLE code :
use Scalar::Util qw(weaken isweak); { my (@a, @b); tie @a, 'Monitor::TestArray'; tie @b, 'Monitor::TestArray'; $a[0] = \@b; $b[0] = \@a; weaken($b[0]); if (isweak($a[0])) { print "\@a is weak\n"; } else { print "\@a is not weak\n"; } if (isweak($b[0])) { print "\@a is weak\n"; } else { print "\@a is not weak\n"; } print STDERR "Leaving scope\n"; } print STDERR "Scope left\n"; package Monitor::TestArray; use Tie::Array; use base 'Tie::StdArray'; sub DESTROY { print STDERR "Monitor::TestArray::DESTROY : $_[0]\n"; } 1;
I get this input :
@a is not weak @a is not weak Leaving scope Scope left Monitor::TestArray::DESTROY : Monitor::TestArray=ARRAY(0x813f2e8) Monitor::TestArray::DESTROY : Monitor::TestArray=ARRAY(0x813f378)
I don't understand why the weaken is inneffective to break the circular reference. If I remove the "tie", it works. But the problem is that I need to know when my variables are destroyed. So I need the "tie" call. Is it a perl bug ? I'm using perl 5.8.3
Thanks,
nothing94

Replies are listed 'Best First'.
Re: Bug with weaken vs tie ???
by gaal (Parson) on Feb 28, 2005 at 16:55 UTC
    Is Monitor::TestArray keeping a hard reference of its own around? (I'm not familiar with Tie::StdArray it is inheriting from and couldn't find mention of it anywhere, so I assume it's local to your project. Perhaps you should show us the implementation?)

    Update: Ah, confusing. Tie::StdArray is defined by Tie::Array. Well, it's worth peeking at the implementation there.

Re: Bug with weaken vs tie ???
by dave_the_m (Monsignor) on Feb 28, 2005 at 19:56 UTC
    In perl, a tie on arrays works by creating a temporary proxy object when you do an array subscript. When you later try to read or write to this object, it triggers the call to FETCH or STORE as appropriate. It is necessary to do it like that to allow code like this to Do The Right Thing:
    sub p1 { print $_[0]} p1($tied_array[0]); # calls FETCH sub p2 { $_[0] = 0 } p2($tied_array[0]); # calls STORE
    The net affect of this is that weaken($b[0]) is actually trying to weaken the temporary proxy object rather then the stored reference. (At least that's what I'm speculating; I've got a cold and it's too much effort to check right now)

    Dave.

      "The net affect of this is that weaken($b[0]) is actually trying to weaken the temporary proxy object rather then the stored reference."

      This is actually what i thing (I think that weaken contains a bug) The actual code from Scalar::Util is :
      void weaken(sv) SV *sv CODE: sv_rvweaken(sv);
      I don't know Perl XS, but my guess is that if it is tied, it must fetch the internal value. This is my guess...