AtExit
view release on metacpan or search on metacpan
lib/AtExit.pm view on Meta::CPAN
sub new {
## Determine if we were called via an object-ref or a classname
my $this = shift;
my $class = ref($this) || $this;
## Bless ourselves into the desired class and perform any initialization
my $self = {
'EXIT_SUBS' => [],
'EXITING' => 0,
'IGNORE_WHEN_EXITING' => 1
};
bless $self, $class;
$self->atexit(@_) if @_;
return $self;
}
sub exit_subs {
## If called as an object, get the object-ref
my $self = (@_ and ref $_[0]) ? shift : \%EXIT_ATTRS;
return $self->{EXIT_SUBS};
}
sub is_exiting {
## If called as an object, get the object-ref
my $self = (@_ and ref $_[0]) ? shift : \%EXIT_ATTRS;
return $self->{EXITING};
}
sub ignore_when_exiting {
## If called as an object, get the object-ref
my $self = (@_ and ref $_[0]) ? shift : \%EXIT_ATTRS;
## Discard the class-name if its the first arg
unless ($self or @_ == 0) {
local $_ = $_[0];
shift if (defined $_ and $_ and /[A-Za-z_]/);
}
$self->{IGNORE_WHEN_EXITING} = shift if @_;
return $self->{IGNORE_WHEN_EXITING};
}
sub atexit {
## If called as an object, get the object-ref
local $_ = ref $_[0];
my $self = ($_ and $_ ne 'CODE') ? shift : \%EXIT_ATTRS;
## Get the remaining arguments
my ($exit_sub, @args) = @_;
return 0 if ($self->{EXITING} and $self->{IGNORE_WHEN_EXITING});
unless (ref $exit_sub) {
## Caller gave us a sub name instead of a sub reference.
## Need to make sure we have the callers package prefix
## prepended if one wasn't given.
my $pkg = '';
$pkg = (caller)[0] . "::" unless $exit_sub =~ /::/o;
## Now turn the sub name into a hard sub reference.
$exit_sub = eval "\\&$pkg$exit_sub";
undef $exit_sub if ($@);
}
return 0 unless (defined $exit_sub) && (ref($exit_sub) eq 'CODE');
## If arguments were given, wrap the invocation up in a closure
my $subref = (@args > 0) ? sub { &$exit_sub(@args); } : $exit_sub;
## Now put this sub-ref on the queue and return what we just registered
unshift(@{ $self->{EXIT_SUBS} }, $subref);
return $subref;
}
sub rmexit {
## If called as an object, get the object-ref
local $_ = ref $_[0];
my $self = ($_ and $_ ne 'CODE') ? shift : \%EXIT_ATTRS;
## Get remaining arguments
my @subrefs = @_;
## Unregister each sub in the given list.
## [ I suppose I could come up with a faster way to do this than
## doing a separate iteration for each argument, but I wont
## worry about that just yet. ]
##
my ($unregistered, $i) = (0, 0);
my $exit_subs = $self->{EXIT_SUBS};
if (@subrefs == 0) {
## Remove *all* exit-handlers
$unregistered = scalar(@$exit_subs);
$exit_subs = $self->{EXIT_SUBS} = [];
}
else {
my $subref;
foreach $subref (@subrefs) {
next unless (ref($subref) eq 'CODE');
## Iterate over the queue and remove the first match
for ($i = 0; $i < @$exit_subs; ++$i) {
if ($subref == $exit_subs->[$i]) {
splice(@$exit_subs, $i, 1);
++$unregistered;
last;
}
}
}
}
return $unregistered;
}
sub do_atexit {
## If called as an object, get the object-ref
my $self = (@_ and ref $_[0]) ? shift : \%EXIT_ATTRS;
$self->{EXITING} = 1;
## Handle atexit() stuff in reverse order of registration
my $exit_subs = $self->{EXIT_SUBS};
( run in 0.513 second using v1.01-cache-2.11-cpan-5511b514fd6 )