fix detecting GD in BEGIN, with tests
[p5sagit/Devel-GlobalDestruction.git] / lib / Devel / GlobalDestruction.pm
CommitLineData
a91e8a78 1package Devel::GlobalDestruction;
2
3use strict;
4use warnings;
5
23d57d81 6our $VERSION = '0.09';
a91e8a78 7
aaccce0c 8use Sub::Exporter::Progressive -setup => {
53daa838 9 exports => [ qw(in_global_destruction) ],
10 groups => { default => [ -all ] },
a91e8a78 11};
12
6e3fd33e 13# we run 5.14+ - everything is in core
14#
eaac10b5 15if (defined ${^GLOBAL_PHASE}) {
62376bb4 16 eval 'sub in_global_destruction () { ${^GLOBAL_PHASE} eq q[DESTRUCT] }; 1'
17 or die $@;
3790e928 18}
6e3fd33e 19# try to load the xs version if it was compiled
20#
9aaf3646 21elsif (eval {
53daa838 22 require XSLoader;
23 XSLoader::load(__PACKAGE__, $VERSION);
24 1;
9aaf3646 25}) {
53daa838 26 # the eval already installed everything, nothing to do
3790e928 27}
9aaf3646 28else {
23135b02 29 # internally, PL_main_start is nulled immediately before entering global destruction
5629eb97 30 # and we can use B to detect that. It will also be null before the main runloop starts,
31 # so we check install a CHECK if needed to detect that.
97415ced 32 require B;
5629eb97 33 my $started = !B::main_start()->isa(q[B::NULL]);
34 unless ($started) {
35 eval 'CHECK { $started = 1 }; 1'
36 or die $@;
37 }
38 eval 'sub in_global_destruction () { $started && B::main_start()->isa(q[B::NULL]) }; 1'
97415ced 39 or die $@;
9aaf3646 40}
41
421; # keep require happy
43
44
45__END__
a91e8a78 46
47=head1 NAME
48
761f3ee2 49Devel::GlobalDestruction - Expose the flag which marks global
a91e8a78 50destruction.
51
52=head1 SYNOPSIS
53
f832e240 54 package Foo;
55 use Devel::GlobalDestruction;
a91e8a78 56
f832e240 57 use namespace::clean; # to avoid having an "in_global_destruction" method
a91e8a78 58
f832e240 59 sub DESTROY {
60 return if in_global_destruction;
a91e8a78 61
f832e240 62 do_something_a_little_tricky();
63 }
a91e8a78 64
65=head1 DESCRIPTION
66
67Perl's global destruction is a little tricky to deal with WRT finalizers
68because it's not ordered and objects can sometimes disappear.
69
70Writing defensive destructors is hard and annoying, and usually if global
71destruction is happenning you only need the destructors that free up non
72process local resources to actually execute.
73
74For these constructors you can avoid the mess by simply bailing out if global
75destruction is in effect.
76
77=head1 EXPORTS
78
aaccce0c 79This module uses L<Sub::Exporter::Progressive> so the exports may be renamed,
80aliased, etc. if L<Sub::Exporter> is present.
a91e8a78 81
82=over 4
83
84=item in_global_destruction
85
761f3ee2 86Returns true if the interpreter is in global destruction. In perl 5.14+, this
87returns C<${^GLOBAL_PHASE} eq 'DESTRUCT'>, and on earlier perls, it returns the
88current value of C<PL_dirty>.
a91e8a78 89
90=back
91
ec94b9e1 92=head1 AUTHORS
a91e8a78 93
94Yuval Kogman E<lt>nothingmuch@woobling.orgE<gt>
95
ec94b9e1 96Florian Ragwitz E<lt>rafl@debian.orgE<gt>
97
aaa7f60f 98Jesse Luehrs E<lt>doy@tozt.netE<gt>
99
9aaf3646 100Peter Rabbitson E<lt>ribasushi@cpan.orgE<gt>
101
aaccce0c 102Arthur Axel 'fREW' Schmidt E<lt>frioux@gmail.comE<gt>
103
140a3884 104Elizabeth Mattijsen E<lt>liz@dijkmat.nlE<gt>
105
a91e8a78 106=head1 COPYRIGHT
107
f832e240 108 Copyright (c) 2008 Yuval Kogman. All rights reserved
109 This program is free software; you can redistribute
110 it and/or modify it under the same terms as Perl itself.
a91e8a78 111
112=cut