From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 79A471FFA7 for ; Fri, 18 Dec 2020 12:09:52 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH 19/26] on_destroy: generic localized END Date: Fri, 18 Dec 2020 12:09:43 +0000 Message-Id: <20201218120950.23272-20-e@80x24.org> In-Reply-To: <20201218120950.23272-1-e@80x24.org> References: <20201218120950.23272-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: 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. --- MANIFEST | 2 ++ lib/PublicInbox/OnDestroy.pm | 16 ++++++++++++++++ t/on_destroy.t | 25 +++++++++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 lib/PublicInbox/OnDestroy.pm create mode 100644 t/on_destroy.t 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;