Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

Perl variable garbage collection

by chinaxing (Acolyte)
on Jul 31, 2013 at 07:16 UTC ( #1047188=perlquestion: print w/ replies, xml ) Need Help??
chinaxing has asked for the wisdom of the Perl Monks concerning the following question:

I have a little confuse about the variable garbage collection in perl in following example :

#!/bin/env perl use v5.14; package MyTestModule { sub foo { my $fh = shift; for(1..100){ say "PUT"; $fh->autoflush(1); print $fh "Heloo\n"; sleep 1; } } } package main; use AnyEvent; use AnyEvent::Fork::Template; my $cv = AnyEvent->condvar; $AnyEvent::Fork::Template->fork->run("MyTestModule::foo", sub { my $fh_fh_fh = shift; my $w_w_w; $w_w_w = AnyEvent->io(fh => $fh_fh_fh, poll => "r", cb => sub { $w_w_w unless 1; sysread $fh_fh_fh, my $rslt, 10; say "GOT:", $rslt; } ); }); $cv->wait;

In above code, if I remove the $w_w_w, then because of the AnyEvent->io create a object, its reference become zero, then it will be reclaimed by perl, which make the code not work ( the cb will not be called );

... $AnyEvent::Fork::Template->fork->run("MyTestModule::foo", sub { my $fh_fh_fh = shift; AnyEvent->io(fh => $fh_fh_fh, poll => "r", cb => sub { sysread $fh_fh_fh, my $rslt, 10; say "GOT:", $rslt; } ); }); ...

then I assign it to scalar $w_w_w, but I dose not need the $w_w_w in the callback. but the following code not working(callback will not be called):

$AnyEvent::Fork::Template->fork->run("MyTestModule::foo", sub { my $fh_fh_fh = shift; my $w_w_w; $w_w_w = AnyEvent->io(fh => $fh_fh_fh, poll => "r", cb => sub { sysread $fh_fh_fh, my $rslt, 10; say "GOT:", $rslt; } ); });

so I add one line code in the callback(just you can see it in the front of this requestion) :

$w_w_w unless 1;
because the assertion will always be false, so it will not ran, I think the perl compiler/interpreter will optimize this line code ( drop it ), then the $w_w_w 's reference count will be zero. and the callback will not be called also.

but it works. so I hope someone can explain this .(the following is a dump of perl -ODeparse

perl -MO=Deparse t2.pl sub BEGIN { require v5.14; } package MyTestModule; sub foo { use strict; no feature; use feature ':5.12'; my $fh = shift(); foreach $_ (1 .. 100) { say 'PUT'; $fh->autoflush(1); print $fh "Heloo\n"; sleep 1; } } package main; use strict; no feature; use feature ':5.12'; {;}; use AnyEvent; use AnyEvent::Fork::Template; my $cv = 'AnyEvent'->condvar; $AnyEvent::Fork::Template->fork->run('MyTestModule::foo', sub { my $fh_fh_fh = shift(); my $w_w_w; $w_w_w = 'AnyEvent'->io('fh', $fh_fh_fh, 'poll', 'r', 'cb', sub { '???'; sysread $fh_fh_fh, my $rslt, 10; say 'GOT:', $rslt; } ); } ); $cv->wait;

Comment on Perl variable garbage collection
Select or Download Code
Re: Perl variable garbage collection
by choroba (Abbot) on Jul 31, 2013 at 07:54 UTC
    Crossposted at StackOverflow. It is considered polite to inform about crossposting so hackers not attending both sites do not waste their efforts solving a problem already closed at the other end of the Internets.
    لսႽ ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Perl variable garbage collection
by rjt (Deacon) on Jul 31, 2013 at 09:31 UTC

    From B::Deparse:

    Optimised away statements are rendered as '???'. This includes statements that have a compile-time side-effect

    The crux of this is that, yes, Perl does optimize away the statement $w_w_w unless 1;, but it still puts it on your sub's pad (it does even if you don't say $w_w_w anywhere in your sub's code, but it will be undef when it goes out of scope in the enclosing block). But any mention within that anonymous sub will keep the reference count (because anon subs are created at runtime), and prevent GC. Even though the statement itself does nothing, a reference to your AnyEvent object does exist. The '???' you see isn't the whole story. Try to run the deparse'd code if you need confirmation that there is (was) more going on than an optimized-away statement.

    Or, for a little introspection, add the following to the body of your cb sub:

    use PadWalker qw/peek_my/; use Data::Dump qw/dump/; state $scope_printed = 0; if (not $scope_printed++) { my $my_vars = peek_my(0); while (my ($var, $ref) = each %{ $my_vars }) { printf "%15s => %s\n", $var, dump $ref; } }

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1047188]
Approved by Corion
Front-paged by rjt
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (13)
As of 2014-12-18 08:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (44 votes), past polls