From: Eric Wong Date: Thu, 17 Dec 2020 10:45:12 +0000 (+0000) Subject: on_destroy: generic localized END X-Git-Tag: v1.7.0~1471^2~10 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=7e7f4bfca5f2ef0d123445e074280f5e65cdfb85;p=public-inbox.git on_destroy: generic localized END This is a localized version of the process-wide END{}, but runs at the end of variable scope. A subroutine ref and arguments may be passed, which allows us to avoid anonymous subs and problems they cause. It's similar to `defer' or `ensure' in other languages; Perl can rely on deterministic destructors due to refcounting. --- diff --git a/MANIFEST b/MANIFEST index 29b47843..8e870c22 100644 --- a/MANIFEST +++ b/MANIFEST @@ -181,6 +181,7 @@ lib/PublicInbox/NNTP.pm lib/PublicInbox/NNTPD.pm lib/PublicInbox/NNTPdeflate.pm lib/PublicInbox/NewsWWW.pm +lib/PublicInbox/OnDestroy.pm lib/PublicInbox/Over.pm lib/PublicInbox/OverIdx.pm lib/PublicInbox/ProcessPipe.pm @@ -343,6 +344,7 @@ t/nntpd-v2.t t/nntpd.t t/nodatacow.t t/nulsubject.t +t/on_destroy.t t/over.t t/plack-2-txt-bodies.eml t/plack-attached-patch.eml diff --git a/lib/PublicInbox/OnDestroy.pm b/lib/PublicInbox/OnDestroy.pm new file mode 100644 index 00000000..841f87d4 --- /dev/null +++ b/lib/PublicInbox/OnDestroy.pm @@ -0,0 +1,16 @@ +# Copyright (C) 2020 all contributors +# License: AGPL-3.0+ + +package PublicInbox::OnDestroy; + +sub new { + shift; # ($class, $cb, @args) + bless [ @_ ], __PACKAGE__; +} + +sub DESTROY { + my ($cb, @args) = @{$_[0]}; + $cb->(@args) if $cb; +} + +1; diff --git a/t/on_destroy.t b/t/on_destroy.t new file mode 100644 index 00000000..8b85b48e --- /dev/null +++ b/t/on_destroy.t @@ -0,0 +1,25 @@ +#!perl -w +use strict; +use v5.10.1; +use Test::More; +require_ok 'PublicInbox::OnDestroy'; +my @x; +my $od = PublicInbox::OnDestroy->new(sub { push @x, 'hi' }); +is_deeply(\@x, [], 'not called, yet'); +undef $od; +is_deeply(\@x, [ 'hi' ], 'no args works'); +$od = PublicInbox::OnDestroy->new(sub { $x[0] = $_[0] }, 'bye'); +is_deeply(\@x, [ 'hi' ], 'nothing changed while alive'); +undef $od; +is_deeply(\@x, [ 'bye' ], 'arg passed'); +$od = PublicInbox::OnDestroy->new(sub { @x = @_ }, qw(x y)); +undef $od; +is_deeply(\@x, [ 'x', 'y' ], '2 args passed'); + +if (my $nr = $ENV{TEST_LEAK_NR}) { + for (0..$nr) { + $od = PublicInbox::OnDestroy->new(sub { @x = @_ }, qw(x y)); + } +} + +done_testing;