Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Re^4: is there a way to ensure some code is the last thing that is run? (SUPEREND)

by LanX (Saint)
on Feb 03, 2017 at 13:13 UTC ( [id://1180959]=note: print w/replies, xml ) Need Help??


in reply to Re^3: is there a way to ensure some code is the last thing that is run? (monkey patching)
in thread is there a way to ensure some code is the last thing that is run?

The following will demonstrate an approach to define a &SUPEREND::DESTROY which is run after all other global DESTROY()s happend.

use strict; use warnings; package Blubb; sub new { my $this = bless {a=>42}; $this->{circular} = $this; } sub DESTROY { warn "DESTROY ". __PACKAGE__; } package SUPEREND; no warnings 'redefine'; my $orig_destroy= \&Blubb::DESTROY; my $persist = bless { count=>0}; *Blubb::DESTROY= sub { $orig_destroy->(@_); warn "Mini END"; $persist->{count}++; }; sub DESTROY { warn "DESTROY after $_[0]->{count} destroys ". __PACKAGE__; } package MAIN; my $b = Blubb->new; my $c = Blubb->new; my $d = Blubb->new;

DESTROY Blubb at c:/tmp/pm/destruct_end.pl line 12 during global destr +uction. Mini END at c:/tmp/pm/destruct_end.pl line 25 during global destructio +n. DESTROY Blubb at c:/tmp/pm/destruct_end.pl line 12 during global destr +uction. Mini END at c:/tmp/pm/destruct_end.pl line 25 during global destructio +n. DESTROY Blubb at c:/tmp/pm/destruct_end.pl line 12 during global destr +uction. Mini END at c:/tmp/pm/destruct_end.pl line 25 during global destructio +n. DESTROY after 3 destroys SUPEREND at c:/tmp/pm/destruct_end.pl line 33 + during global destruction.

Please note, that this can be extended to be a generic solution, because SUPEREND could parse all packages available and monkeypatch all DESTROYs there (if existent)

Since $persist is referenced it's DESTROY will be run last.

For syntactic sugar one could also make SUPEREND export a function SUPEREND(&) accepting a codeblock which is run by the DESTROY of $persist.

Cheers Rolf
(addicted to the Perl Programming Language and ☆☆☆☆ :)
Je suis Charlie!

Replies are listed 'Best First'.
Re^5: is there a way to ensure some code is the last thing that is run? (SUPEREND)
by morgon (Priest) on Feb 03, 2017 at 15:32 UTC
    I think in the general case you cannot have a SUPEREND or something like that.

    The reason is that this SUPEREND could again create an object and the destructor of that would again run later.

      > The reason is that this SUPEREND could again create an object and the destructor of that would again run later.

      I'm still wondering what you mean.

      This package is guaranteed to run the last possible (Perl coded) DESTROY, because the ref counter of $persist will only turn 0 after all wrapper ran. (see proof of concept)

      And you can put your desired code in that DESTROY.

      Furthermore you have full control of "SUPEREND" and all "created objects" (which would be handled by the same DESTROY() anyway)

      Of course there is still destruction happening afterwards, namely subs and package variables, but these are hard coded.

      And I wonder how you possibly want to run any code after destruction of subs???

      You stated you need to run the code to fix issues with misbehaving foreign modules.

      If this doesn't help, then it's most probably an XY Problem on your side

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

      > and the destructor of that would again run later.

      ? That is how it works!

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

        But it only works because you know up-front that it's the destructor of a particular class that you need to handle.

        A true SUPEREND-feature should work without such knowledge and that is I believe not possible.

Re^5: is there a way to ensure some code is the last thing that is run? (SUPEREND)
by Anonymous Monk on Feb 03, 2017 at 14:22 UTC
    Lastestdestructor not superend
      > Lastestdestructor

      Rather LastDestructor.

      Or END_OF_DESTRUCTION or even ARMAGEDD_OFF

      Cheers Rolf
      (addicted to the Perl Programming Language and ☆☆☆☆ :)
      Je suis Charlie!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1180959]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2024-03-28 23:38 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found