Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Controlling the order of object destruction

by metaperl (Curate)
on Dec 10, 2009 at 16:24 UTC ( [id://812228]=perlquestion: print w/replies, xml ) Need Help??

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

Could someone point me to the specific place in the Perl docs where is guarantees that lexicals in the _same_ scope will be destroyed in LIFO order?

I.e., in the code below, are we guaranteed that the section labled "LINEAR CODE" will behave the same vis-a-vis object destruction as "CONTROL ORDER OF DESTRUCTION"

use XML::Writer::Nest; use strict; use warnings; my $writer = new XML::Writer; #### LINEAR CODE my $level1 = XML::Writer::Nest->new(tag => 'level1', writer => $writer + ); my $level2 = $level1->nest ('level2'); my $level3 = $level1->nest('level3'); #### CONTROL ORDER OF DESTRUCTION { my $level1 = XML::Writer::Nest->new(tag => 'level1', writer => $writ +er ); { my $level2 = $level1-> nest ('level2'); { my $level3 = $level2->nest('level3'); } } }

Replies are listed 'Best First'.
Re: Controlling the order of object destruction
by ikegami (Patriarch) on Dec 10, 2009 at 17:44 UTC

    Could someone point me to the specific place in the Perl docs where is guarantees that lexicals in the _same_ scope will be destroyed in LIFO order?

    There is no such guarantee. In fact, it's easy to disprove.

    sub DESTROY { print "Destroying $_[0][0]\n"; } { my $x = bless [ '$x' ]; my $y = bless [ '$y' ]; $x->[1] = $y; } print("\n"); { my $x = bless [ '$x' ]; my $y = bless [ '$y' ]; $y->[1] = $x; }
    Destroying $x Destroying $y Destroying $y Destroying $x

    What is guaranteed is that an object won't be destroyed if anything still references it. If the level 1 object contains a reference to the level 2 object, and the level 2 object contains a reference to the level 3 object, the level 1 object is guaranteed to be destroyed before the level 2 object, and the level2 object is guaranteed to be destroyed before the level 3 object.

    sub DESTROY { print "Destroying $_[0][0]\n"; } { my $l3 = bless [ 'l3' ]; my $l2 = bless [ 'l2', $l3 ]; my $l1 = bless [ 'l1', $l2 ]; } print("\n"); { my $l1 = bless [ 'l1' ]; $l1->[1] = my $l2 = bless [ 'l2' ]; $l2->[1] = my $l3 = bless [ 'l3' ]; }
    Destroying l1 Destroying l2 Destroying l3 Destroying l1 Destroying l2 Destroying l3

    There is an exception. If variables survive until global destruction (beyond the outermost lexical scope), all bets are off. This can occur if there's a reference cycle, if it's package variable, or if it's referenced (directly or not) by a package variable.

    sub DESTROY { print "Destroying $_[0][0]\n"; } my $x = bless [ '$x' ]; my $y = bless [ '$y' ]; $y->[1] = $y; # cycle our $z = bless [ '$z' ]; # pkg var END { print "Entering global destruction\n" }
    $ perl a.pl Destroying $x Entering global destruction Destroying $z # Can occur in any order Destroying $y #
Re: Controlling the order of object destruction
by dave_the_m (Monsignor) on Dec 10, 2009 at 17:19 UTC
    The order is not guaranteed, although the current behaviour happens to be that the reference count decrement is in reverse order of execution of the corresponding 'my' expressions. For example:
    sub DESTROY { print "$_[0][0] destroyed\n" } { my $x1 = bless [ "x1" ]; goto L2; L1: my $x2 = bless [ "x2" ]; goto L3; L2: my $x3 = bless [ "x3" ]; goto L1; L3: } __END__ x2 destroyed x3 destroyed x1 destroyed

    Dave.

Re: Controlling the order of object destruction
by MidLifeXis (Monsignor) on Dec 10, 2009 at 16:41 UTC

    I am not sure (but could be wrong) that your assertion about LIFO order is correct. If I remember correctly, all that is guaranteed is that an object may (note that I didn't say will) only be destroyed when there is no longer a reference pointing to it.

    This is why objects with circular references need to use special tricks (like weaken or similar) to free memory.

    --MidLifeXis

      I am not sure (but could be wrong)
      yes, I'm not sure either. I appreciate your input. I definitely want a reference in the docs if possible.
      all that is guaranteed is that an object may (note that I didn't say will) only be destroyed when there is no longer a reference pointing to it.
      yes, that's why I used braces in the second part of the code - to control the order of reference loss.

        Neither MidLifeXis nor ikegami's statements seem to imply a guarantee that an object will be immediately be destroyed when the last reference goes away though.

        So even in your second case it would be in theory possible that the objects are freed in a different order than what you're expecting.

        So there still two questions that might be interesting: 1) does the spec mandate object destruction as soon as there's no reference left; and 2) do all current implementations (including Activestate) behave the same way?

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (5)
As of 2024-03-28 13:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found