File Coverage

blib/lib/Ref/Store/PP/Magic.pm
Criterion Covered Total %
statement 76 83 91.5
branch 21 28 75.0
condition 16 24 66.6
subroutine 16 17 94.1
pod 0 4 0.0
total 129 156 82.6


line stmt bran cond sub pod time code
1             package Ref::Store::PP::Magic;
2 1     1   5 use strict;
  1         2  
  1         21  
3 1     1   4 use warnings;
  1         2  
  1         22  
4 1     1   441 use Variable::Magic qw(cast dispell wizard getdata);
  1         764  
  1         60  
5 1     1   6 use Scalar::Util qw(weaken refaddr reftype isweak);
  1         2  
  1         41  
6 1     1   5 use base qw(Exporter);
  1         2  
  1         45  
7 1     1   5 use Data::Dumper;
  1         2  
  1         33  
8 1     1   4 use Log::Fu;
  1         2  
  1         10  
9 1     1   41 use Devel::Peek;
  1         2  
  1         7  
10 1     1   74 use Devel::GlobalDestruction;
  1         2  
  1         6  
11              
12 1         7 use Constant::Generate [qw(
13             IDX_KEY
14             IDX_TARGET
15 1     1   70 )];
  1         2  
16              
17             our @EXPORT = qw(
18             hr_pp_trigger_register
19             hr_pp_trigger_free
20             hr_pp_trigger_unregister
21             hr_pp_trigger_replace_key
22             hr_pp_purge
23             );
24              
25             our $Wizard;
26              
27             sub _init_wizard {
28             $Wizard = wizard(
29 92     92   204 data => sub { $_[1] },
30 1     1   5 free => \&trigger_fire
31             );
32             }
33              
34             _init_wizard();
35              
36             sub hr_pp_purge {
37 0     0 0 0 my ($ref) = @_;
38 0         0 &dispell($ref, $Wizard);
39             }
40              
41             sub trigger_fire {
42 56     56 0 3163 my ($ref,$actions) = @_;
43 56         102 foreach (@$actions) {
44 108         177 my ($key,$target) = @$_;
45            
46 108 100 66     392 unless (defined $target && defined $key) {
47 1         3 next;
48             }
49            
50 107 100       282 if(reftype $target eq 'HASH') {
    50          
    50          
51 104 50       195 if(ref $key) {
52 0         0 $key = $key+0;
53             }
54 104         242 delete $target->{$key};
55             } elsif (reftype $target eq 'ARRAY') {
56 0         0 delete $target->[$key+0];
57             } elsif (reftype $target eq 'CODE') {
58 3         11 $target->($ref,$key);
59             } else {
60 0         0 die "Unknown target $target";
61             }
62             }
63 56         275 @$actions = ();
64             }
65              
66             sub hr_pp_trigger_unregister {
67 91     91 0 148 my ($ref,$target,$key) = @_;
68 91 50       202 if(!defined $target) {
69 0 0       0 if(in_global_destruction) {
70 0         0 return;
71             }
72             }
73            
74 91         171 my $actions = &getdata($ref, $Wizard);
75 91 100       191 return unless $actions;
76            
77 84         109 my $i = $#{$actions};
  84         132  
78            
79 84         182 while($i >= 0) {
80 85         119 my ($ekey,$etarget) = @{$actions->[$i]};
  85         153  
81 85 100 100     571 if(defined $etarget && $target eq $etarget &&
      66        
      66        
82             (!defined $key) || ($key eq $ekey))
83             {
84 81         111 splice(@{$actions}, $i);
  81         124  
85 81         160 last;
86             }
87 4         11 $i--;
88             }
89            
90 84 100       214 if(!@$actions) {
91 36 50 33     221 &dispell($ref, $Wizard) if (defined $ref && ref $Wizard);
92             }
93             }
94              
95             sub hr_pp_trigger_register {
96            
97 246     246 0 407 my ($ref,$target,$key) = @_;
98 246         458 my $data = &getdata($ref, $Wizard);
99 246         365 my $datum = [];
100 246         485 @$datum[IDX_KEY,IDX_TARGET] = ($key,$target);
101 246         579 weaken($datum->[IDX_TARGET]);
102 246 100       497 weaken($datum->[IDX_KEY]) if ref $key;
103            
104 246 100       466 if(!$data) {
105 92         175 $data = [ $datum ];
106 92         277 &cast($ref, $Wizard, $data);
107 92         199 return;
108             }
109            
110 154         244 foreach (@$data) {
111 222         347 my ($ekey,$etarget) = @$_;
112 222 100 33     1241 if (defined $etarget && defined $ekey &&
      66        
      100        
113             $target == $etarget && $key eq $ekey) {
114 57         147 return;
115             }
116             }
117 97         248 push @$data, $datum;
118             }
119              
120 1     1   678 use Carp qw(cluck);
  1         2  
  1         47  
121              
122             #This one exists primarily for thread duplication
123             #sub hr_pp_trigger_replace_key {
124             # my ($ref,$key,$target,$newkey) = @_;
125             #
126             # my $data = &getdata($ref,$Wizard);
127             # if(!$data) {
128             # cluck("");
129             # log_warn("No data yet? ($ref)");
130             # hr_pp_trigger_register($ref,$key,$target);
131             # log_warn("Casted!");
132             # return;
133             # }
134             #
135             # foreach (@$data) {
136             # my ($ekey,$etarget) = @$_;
137             # if($etarget == $target && $ekey eq $key) {
138             # $_->[IDX_KEY] = $key;
139             # weaken($_->[IDX_KEY]) if ref $key;
140             # return;
141             # }
142             # }
143             # hr_pp_trigger_register($ref,$key,$target);
144             #}
145              
146             1;