The real fix for RT#73402 (abaondon tie %^H entirely), FC++
[p5sagit/namespace-clean.git] / lib / namespace / clean / _PP_OSE.pm
1 package # hide from the pauses
2   namespace::clean::_PP_OSE;
3
4 use warnings;
5 use strict;
6
7 use namespace::clean::_PP_SG;
8 use Tie::Hash;
9 use Hash::Util::FieldHash 'fieldhash';
10
11 # Hash::Util::FieldHash is not deleting elements in void context. When
12 # you call delete() in non-void context, a mortal scalar is returned. A
13 # mortal scalar is one whose reference count decreases at the end of the
14 # current statement. During scope exit, â€˜statement’ is not clearly
15 # defined, so more scope unwinding could happen before the mortal gets
16 # freed.
17 # By tying it and overriding DELETE, we can force the deletion into
18 # void context.
19
20 fieldhash my %hh;
21
22 {
23   package namespace::clean::_TieHintHashFieldHash;
24   use base 'Tie::StdHash';
25   sub DELETE {
26     shift->SUPER::DELETE(@_);
27     1; # put the preceding statement in void context
28   }
29 }
30
31
32 sub on_scope_end (&) {
33   $^H |= 0x020000;
34
35   tie(%hh, 'namespace::clean::_TieHintHashFieldHash')
36     unless tied %hh;
37
38   push @{$hh{\%^H} ||= []},
39     namespace::clean::_PP_SG->arm(shift);
40 }
41
42 1;