Weaken references in Perl
In case you need circular structures in Perl, you should known about Scalar::Util and it’s weaken
function.
See this example:
package T;
sub DESTROY {
my $self = shift;
print STDERR "Bye bye: $self->{name}\n";
}
package main;
use Scalar::Util qw( weaken );
{
my $a = bless { name => 'a' }, 'T';
my $b = bless { name => 'b' }, 'T';
$a->{b} = $b;
$b->{a} = $a;
}
print "Should see a destroy 'a' and 'b', but you wont...\n";
{
my $c = bless { name => 'c' }, 'T';
my $d = bless { name => 'd' }, 'T';
$c->{d} = weaken($d);
$d->{c} = weaken($c);
}
print "Should see a destroy 'c' and 'd'!\n";
print "Now you'll see a destroy 'a' and 'b'\n";
The output is this:
Should see a destroy 'a' and 'b', but you wont...
Bye bye: d
Bye bye: c
Should see a destroy 'c' and 'd'!
Now you'll see a destroy 'a' and 'b'
Bye bye: b
Bye bye: a
The problem is that in the first block, although the $a
and $b
are no longer in scope, each one holds a reference to the other, and that prevents them both from being destroyed.
In the second block, each one of $c
and $d
takes a weak reference to each other. Weak references don’t increment the reference count internal to all Perl variables, so at the end of the block, they are correctly destroyed.
You’ve warned.