http://qs1969.pair.com?node_id=103526


in reply to Re: Re (tilly) 1: Tie & Destroy, OOP
in thread Tie & Destroy, OOP

Lexical or not, the question is whether the data is garbage collected before the end of the program. If it is done before then you get reliable destruction mechanics that we all know and love. If it is done in the final global destruction, data is terminated with prejudice at random.

BTW another solution that comes to mind is to use a flyweight pattern for your objects. That puts all of your current objects into a convenient hash that you can iterate through in an END block to do cleanup. Doing things that way gives you 2 wins. Better encapsulation, and it solves the global destruction problem in a way that is more likely to work across versions of Perl.

Replies are listed 'Best First'.
(tye)Re: Tie & Destroy, OOP
by tye (Sage) on Aug 10, 2001 at 01:05 UTC

    Just to be clear: lexical variables don't suffer from this problem, even lexical variables at file scope. That implies that lexicals are destroyed before global destruction begins (which I believe to be true but I haven't verified that beyond testing that lexicals don't suffer from this problem).

    To be extra clear: destroying a lexical variable won't necessarilly destroy the object that it references. If you have other references to that same object and any of those reference manage to survive until global destruction, then your object will survive until then as well (and can so could then suffer from misordered destructions).

            - tye (but my friends call me "Tye")
      Not true. On 5.005_03 try this:
      my $foo = be({name => "foo"}); my $bar = be({name => "bar", data => $foo}); my $baz = be({name => "baz", data => $bar}); sub gotcha { $bar->{"bar can't go"} = "until this function is cleaned up"; } sub be { return bless shift; } sub DESTROY { my $self = shift; print "$self->{name} died\n"; } __END__ on 5.005_03 for me prints: baz died foo died bar died
      Note that $foo is going away before $bar. Remove the function holding $bar to global destruction and everything will clean up properly. Make them all global and you will again run into trouble.

        You can also just store a reference to your lexical in a global to simulate the same thing. Yes, "global" "closures" are probably harder to notice than global variables, but the same basic principle applies: keeping a reference to something around prevents it from being destroyed (until global destruction, of course).

        But none of that changes the fact that you can avoid the problems with misordered destruction by using only lexical (including making sure that any references to said lexicals are also only in lexicals, etc.). That is a very practical bit of information.

        Also, current versions of Perl create a reference loop for "real" closures and so they would also cause you problems (as well as leaking memory if you create lots of closures).

                - tye (but my friends call me "Tye")