in reply to Re: when is destroy function called
in thread when is destroy function called
I lean towards the first reading. I think the reason that the destroy method executes after print completes is because a reference to the object is placed on the stack, and the reference count goes to zero when the parameters are cleared from the stack.
Calling destroy immediately is simpler than maintaining a to-do list for later processing. If I were to write perl, I'd choose the simpler method. (Of course, I can't offer any evidence either way--it's just my gut feeling.)
...roboticus
When your only tool is a hammer, all problems look like your thumb.
|
---|
Replies are listed 'Best First'. | |||
---|---|---|---|
Re^3: when is destroy function called
by Athanasius (Archbishop) on Mar 02, 2013 at 17:28 UTC | |||
I think the reason that the destroy method executes after print completes is because a reference to the object is placed on the stack, and the reference count goes to zero when the parameters are cleared from the stack. So the idea is that DESTROY is called immediately when the reference count falls to zero, but that the decrementing of the reference count does not occur immediately upon the call to undef? That sounds reasonable, but I’m not sure which stack is meant. It can’t be the subroutine’s parameter list:
Output:
Can you clarify what you mean by “a reference to the object is placed on the stack”?
| [reply] [d/l] [select] | ||
by roboticus (Chancellor) on Mar 02, 2013 at 21:35 UTC | |||
Yeah, I could've been more clear... I meant that when setting up the print statement:
that I suspect that perl may be putting a reference to the thing $enemy refers to on the stack for the purpose of calling the obey() method (and possibly for the undef thing, too). So that we'd have something like this:
At this point, I'm guessing the stack contains a reference to the Dalek that $enemy also points to, so it can call the obey method.
Here, we've already executed the obey() method so the string gets printed, and we've just executed undef, so the link between $enemy and the Dalek is now broken. But the argument stack for print still holds the reference to the Dalek.
Most of the argument stack for the print statement is gone, the next item to go is the reference of interest. (Note: the reference count to the 'Exterminaor' string has already dropped back to 1.) So perl dutifully reduces the references count for the item on the stack, and notices the count went to 0:
...at which point it tells the Dalek to go DESTROY itself. While it destroys itself, it discards the reference to the Phaser (reducing its reference count):
The Phaser still has a reference, so it's going to stick around. When the DESTROY method returns, perl then frees the Dalek memory, and continues to remove items from the argument stack:
Read more... (1181 Bytes)
The results are a bit tedious to read through, though: Read more... (3 kB)
Update: I went ahead and updated the diagram to show the reference counts for the 'Exterminated' string as well. It make the node a bit longer, but I think it helps illustrate things. I also added a couple readmore tags to make a long post somewhat shorter. ...roboticus When your only tool is a hammer, all problems look like your thumb. | [reply] [d/l] [select] | ||
by Athanasius (Archbishop) on Mar 04, 2013 at 04:10 UTC | |||
Hello roboticus, Thanks for taking so much trouble in your explanation! I’ve been trying — with limited success :-( — to wrap my head around it for about a day now, which is why I haven’t replied sooner. I’m confused by this: Here, we’ve already executed the obey() method so the string gets printed, and we’ve just executed undef, so the link between $enemy and the Dalek is now broken. But the argument stack for print still holds the reference to the Dalek. I would have expected that each argument is popped from the stack as it is processed, so that its reference count is decremented as it leaves the stack. But I admit I don’t really know how all this works. Your use of Devel::Peek is interesting. (Incidentally, I think the expression ${shift}->{theVal} should be shift->{theVal}?) Looking at the reference counts, I can’t see the increment you predict between “before print” and “Do the print” — what should I be looking at? I did find this in the section Reference Counts and Mortality in perlguts: There are some convenience functions available that can help with the destruction of xVs. These functions introduce the concept of "mortality". An xV that is mortal has had its reference count marked to be decremented, but not actually decremented, until "a short time later". Generally the term "short time later" means a single Perl statement, such as a call to an XSUB function. If that passage is relevant to the situation we’ve been discussing, it supports your idea that it is the decrementing of the reference count to zero which is delayed until the print statement completes, and that, when the reference count reaches zero, the destructor is called immediately.
| [reply] [d/l] [select] | ||
by roboticus (Chancellor) on Mar 06, 2013 at 02:37 UTC | |||
by Athanasius (Archbishop) on Mar 06, 2013 at 13:11 UTC | |||
|