File Coverage

blib/lib/Tie/Hash/Cache/MRU.pm
Criterion Covered Total %
statement 50 158 31.6
branch 15 74 20.2
condition 7 16 43.7
subroutine 11 24 45.8
pod 3 3 100.0
total 86 275 31.2


line stmt bran cond sub pod time code
1             package Tie::Hash::Cache::MRU;
2              
3 1     1   7081 use 5.006001;
  1         5  
  1         39  
4 1     1   5 use strict;
  1         1  
  1         29  
5 1     1   5 use warnings;
  1         458  
  1         340  
6              
7              
8             our $VERSION = '0.02';
9              
10             sub CURRENT(){0};
11             sub OLD(){1};
12             sub TIME(){2}
13             sub SIZE(){3};
14             sub LIFE(){4};
15             sub HASH(){5};
16             # FETCH, STORE, EXISTS, DELETE, FIRSTKEY, NEXTKEY, CLEAR. DESTROY
17             sub S(){6};
18             sub F(){7};
19             sub D(){8};
20             sub E(){9};
21             sub C(){10};
22             sub FK(){11};
23             sub NK(){12};
24             sub DE(){13};
25              
26             sub TIEHASH {
27              
28 2     2   887 my $pack = shift;
29 2         7 my %arg = @_;
30              
31 1     1   6 no warnings;
  1         1  
  1         579  
32 2         12 my @obj = ( {}, {}, {},
33             @arg{qw/SIZE LIFE HASH
34             STORE FETCH DELETE EXISTS CLEAR FIRSTKEY NEXTKEY DESTROY/});
35              
36 2 100       9 defined $obj[LIFE] or delete $obj[TIME];
37 2   50 12   18 $obj[F] ||= sub($){$obj[HASH]->{$_[0]}};
  12         69  
38 2   50 0   13 $obj[S] ||= sub($$){$obj[HASH]->{$_[0]} = $_[1]};
  0         0  
39 2   50 0   11 $obj[D] ||= sub($){delete $obj[HASH]->{$_[0]}};
  0         0  
40 2   50 1   13 $obj[E] ||= sub($){exists $obj[HASH]->{$_[0]}};
  1         10  
41 2 50   0   11 defined $obj[C] or $obj[C] = sub(){%{$obj[HASH]} = () };
  0         0  
  0         0  
42              
43              
44 2         12 bless \@obj, $pack;
45              
46             }
47              
48             my $NOTEXIST;
49              
50             sub FETCH { # obj, key
51              
52 14 100   14   56 if($_[0]->[LIFE]){
53              
54 3 100 100     26 if(exists $_[0]->[TIME]->{$_[1]}
55             and
56             (time() - $_[0]->[TIME]->{$_[1]}) > $_[0]->[LIFE] ){
57              
58 1         15 $_[0]->[CURRENT]->{$_[1]} =
59 1         4 &{$_[0]->[E]}($_[1])?
60 1 50       3 &{$_[0]->[F]}($_[1]):
61             \$NOTEXIST;
62             };
63 3         16 $_[0]->[TIME]->{$_[1]} = time;
64             };
65              
66 14 100       40 if (exists $_[0]->[CURRENT]->{$_[1]}){
67 3 50       16 $_[0]->[CURRENT]->{$_[1]} eq \$NOTEXIST
68             and return undef;
69 3         21 return $_[0]->[CURRENT]->{$_[1]}
70             };
71 11 50       25 if (exists $_[0]->[OLD]->{$_[1]}){
72 0 0 0     0 $_[0]->[OLD]->{$_[1]} eq \$NOTEXIST
73             and $_[0]->[CURRENT]->{$_[1]} = \$NOTEXIST
74             and return undef;
75             return
76 0         0 $_[0]->[CURRENT]->{$_[1]} =
77             delete $_[0]->[OLD]->{$_[1]}
78             };
79 1     1   5 no warnings;
  1         2  
  1         184  
80 11 100       11 if (%{$_[0]->[CURRENT]} > $_[0]->[SIZE]){
  11         53  
81 1 50       4 if($_[0]->[LIFE]){
82 0         0 delete @{$_[0]->[TIME]}{
83 0         0 grep { ! exist $_[0]->[CURRENT]->{$_} }
  0         0  
84 0         0 keys %{ $_[0]->[OLD] }
85             };
86             };
87 1         3 $_[0]->[OLD] = $_[0]->[CURRENT];
88 1         2 $_[0]->[CURRENT] = {};
89             };
90 11         24 $_[0]->[CURRENT]->{$_[1]} =
91 11         18 &{$_[0]->[F]}($_[1]);
92             }
93              
94             sub STORE { # obj, key, value
95 1     1   4 no warnings;
  1         2  
  1         15495  
96 0 0   0     if (%{$_[0]->[CURRENT]} > $_[0]->[SIZE]){
  0            
97 0 0         if($_[0]->[LIFE]){
98 0           delete @{$_[0]->[TIME]}{
99 0           grep { ! exist $_[0]->[CURRENT]->{$_} }
  0            
100 0           keys %{ $_[0]->[OLD] }
101             };
102             };
103 0           $_[0]->[OLD] = $_[0]->[CURRENT];
104 0           $_[0]->[CURRENT] = {};
105             };
106 0 0         $_[0]->[LIFE] and $_[0]->[TIME]->{$_[1]} = time;
107 0           $_[0]->[CURRENT]->{$_[1]} = $_[2];
108 0           &{$_[0]->[S]}(@_[1,2]);
  0            
109             }
110             sub EXISTS {
111 0 0   0     if($_[0]->[LIFE]){
112              
113 0 0 0       if(exists $_[0]->[TIME]->{$_[1]}
114             and
115             (time() - $_[0]->[TIME]->{$_[1]}) > $_[0]->[LIFE] ){
116              
117 0           $_[0]->[CURRENT]->{$_[1]} =
118 0           &{$_[0]->[E]}($_[1])?
119 0 0         &{$_[0]->[F]}($_[1]):
120             \$NOTEXIST;
121             };
122 0           $_[0]->[TIME]->{$_[1]} = time;
123             };
124 0 0         if (exists $_[0]->[CURRENT]->{$_[1]}){
125 0 0         $_[0]->[CURRENT]->{$_[1]} eq \$NOTEXIST
126             and return undef;
127            
128 0           return 1
129             };
130 0 0         if (exists $_[0]->[OLD]->{$_[1]}){
131 0           $_[0]->[CURRENT]->{$_[1]} =
132             delete $_[0]->[OLD]->{$_[1]};
133 0 0         $_[0]->[CURRENT]->{$_[1]} eq \$NOTEXIST
134             and return undef;
135 0           return 1;
136             };
137 1     1   28 no warnings;
  1         2  
  1         909  
138 0 0         if (%{$_[0]->[CURRENT]} > $_[0]->[SIZE]){
  0            
139 0 0         if($_[0]->[LIFE]){
140 0           delete @{$_[0]->[TIME]}{
141 0           grep { ! exist $_[0]->[CURRENT]->{$_} }
  0            
142 0           keys %{ $_[0]->[OLD] }
143             };
144             };
145 0           $_[0]->[OLD] = $_[0]->[CURRENT];
146 0           $_[0]->[CURRENT] = {};
147             };
148 0 0         if(&{$_[0]->[E]}($_[1])){
  0            
149 0           $_[0]->[CURRENT]->{$_[1]} =
150 0           &{$_[0]->[F]}($_[1]);
151 0           return 1;
152             }else{
153 0           $_[0]->[CURRENT]->{$_[1]} = \$NOTEXIST;
154 0           return undef;
155             }
156             }
157              
158             sub DELETE {
159 0     0     $_[0]->[CURRENT]->{$_[1]} = \$NOTEXIST;
160 0 0         $_[0]->[LIFE] and $_[0]->[TIME]->{$_[1]} = time;
161 0           &{$_[0]->[D]}($_[1]);
  0            
162              
163             }
164              
165             sub FIRSTKEY {
166 0 0   0     defined $_[0]->[FK] and return &{$_[0]->[FK]}();
  0            
167 0           my $t = tied % { $_[0]->[HASH] };
  0            
168 0 0         $t and return $t->FIRSTKEY();
169 0           keys %{$_[0]->[HASH]};
  0            
170 0           return each %{$_[0]->[HASH]};
  0            
171              
172             }
173              
174             sub NEXTKEY {
175 0 0   0     defined $_[0]->[NK] and return &{$_[0]->[NK]}();
  0            
176 0           my $t = tied % { $_[0]->[HASH] };
  0            
177 0 0         $t and return $t->NEXTKEY($_[1]);
178 0           return each % { $_[0]->[HASH] };
  0            
179             }
180              
181             sub CLEAR {
182 0           %{$_[0]->[CURRENT]} =
  0            
183 0     0     %{$_[0]->[OLD]} = ();
184 0 0         $_[0]->[LIFE] and %{$_[0]->[TIME]} = ();
  0            
185              
186 0           ref( $_[0]->[C]) =~ /CODE/ and
187 0 0         &{$_[0]->[C]}();
188              
189             }
190              
191             sub DESTROY {
192 0 0   0     defined $_[0]->[DE] and &{$_[0]->[DE]}();
  0            
193              
194             }
195              
196              
197              
198             sub CACHE {
199 0     0 1   my $obj = shift;
200              
201 0           %{ $obj->[CURRENT] } =
  0            
202 0           ( %{ $obj->[CURRENT] } , @_ );
203 0 0         if($_[0]->[LIFE]){
204 0           $_[0]->[TIME]->{$_} = time foreach @_;
205             };
206              
207              
208             }
209             sub UNCACHE {
210 0     0 1   my $obj = shift;
211 0           delete @{$obj->[CURRENT]}{@_};
  0            
212 0           delete @{$obj->[OLD]}{@_};
  0            
213 0 0         $obj->[LIFE] and delete @{$obj->[TIME]}{@_};
  0            
214              
215             }
216             sub UPDATE {
217 0     0 1   my $obj = shift;
218 0           my %update = @_;
219 0           my ($k,$v);
220 0           while(($k,$v) = each %update){
221 0 0         if(exists $obj->[CURRENT]->{$k}
222             ){
223 0           $obj->[CURRENT]->{$k} = $v;
224 0           next;
225             };
226 0 0         if(exists $obj->[OLD]->{$k}
227             ){
228 0           $obj->[CURRENT]->{$k} = $v;
229 0           delete $obj->[OLD]->{$k};
230             };
231             };
232 0 0         if($obj->[LIFE]){
233 0           foreach( grep { exists $obj->[CURRENT]->{$_} } keys %update){
  0            
234 0           $obj->[TIME]->{$_} = time;
235              
236             } } }
237              
238              
239             1;
240             __END__