Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Perl variable garbage collection

by chinaxing (Acolyte)
on Jul 31, 2013 at 07:16 UTC ( [id://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;

Replies are listed 'Best First'.
Re: Perl variable garbage collection
by rjt (Curate) 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; } }
Re: Perl variable garbage collection
by choroba (Cardinal) 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.
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
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?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (4)
As of 2024-03-19 06:47 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found