Commit | Line | Data |
b2e54862 |
1 | package # hide from the pauses |
2 | namespace::clean::_PP_OSE; |
3 | |
4 | use warnings; |
5 | use strict; |
6 | |
b2e54862 |
7 | use Tie::Hash; |
8 | use Hash::Util::FieldHash 'fieldhash'; |
9 | |
aabe8f1c |
10 | # Here we rely on a combination of several behaviors: |
11 | # |
12 | # * %^H is deallocated on scope exit, so any references to it disappear |
13 | # * A lost weakref in a fieldhash causes the corresponding key to be deleted |
14 | # * Deletion of a key on a tied hash triggers DELETE |
15 | # |
16 | # Therefore the DELETE of a tied fieldhash containing a %^H reference will |
17 | # be the hook to fire all our callbacks. |
b2e54862 |
18 | |
19 | fieldhash my %hh; |
b2e54862 |
20 | { |
f98a96a1 |
21 | package # hide from pause too |
22 | namespace::clean::_TieHintHashFieldHash; |
b2e54862 |
23 | use base 'Tie::StdHash'; |
24 | sub DELETE { |
4dc0aa54 |
25 | my $ret = shift->SUPER::DELETE(@_); |
26 | $_->() for @$ret; |
27 | $ret; |
b2e54862 |
28 | } |
29 | } |
30 | |
b2e54862 |
31 | sub on_scope_end (&) { |
32 | $^H |= 0x020000; |
33 | |
34 | tie(%hh, 'namespace::clean::_TieHintHashFieldHash') |
35 | unless tied %hh; |
36 | |
aabe8f1c |
37 | push @{ $hh{\%^H} ||= [] }, shift; |
b2e54862 |
38 | } |
39 | |
40 | 1; |